gmshToFoam.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Application
25  gmshToFoam
26 
27 Description
28  Reads .msh file as written by Gmsh.
29 
30  Needs surface elements on mesh to be present and aligned with outside faces
31  of the mesh. I.e. if the mesh is hexes, the outside faces need to be
32  quads.
33 
34  Note: There is something seriously wrong with the ordering written in the
35  .msh file. Normal operation is to check the ordering and invert prisms
36  and hexes if found to be wrong way round.
37  Use the -keepOrientation to keep the raw information.
38 
39  Note: The code now uses the element (cell,face) physical region id number
40  to create cell zones and faces zones (similar to
41  fluentMeshWithInternalFaces).
42 
43  A use of the cell zone information, is for field initialisation with the
44  "setFields" utility.
45 
46 \*---------------------------------------------------------------------------*/
47 
48 #include "argList.H"
49 #include "polyMesh.H"
50 #include "Time.H"
51 #include "polyMesh.H"
52 #include "IFstream.H"
53 #include "cellModeller.H"
54 #include "repatcher.H"
55 #include "cellSet.H"
56 #include "faceSet.H"
57 
58 using namespace Foam;
59 
60 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
61 
62 // Element type numbers
63 static label MSHTRI = 2;
64 static label MSHQUAD = 3;
65 static label MSHTET = 4;
66 static label MSHPYR = 7;
67 static label MSHPRISM = 6;
68 static label MSHHEX = 5;
69 
70 
71 // Skips till end of section. Returns false if end of file.
72 bool skipSection(IFstream& inFile)
73 {
74  string line;
75  do
76  {
77  inFile.getLine(line);
78 
79  if (!inFile.good())
80  {
81  return false;
82  }
83  }
84  while (line.size() < 4 || line.substr(0, 4) != "$End");
85 
86  return true;
87 }
88 
89 
90 void renumber
91 (
92  const Map<label>& mshToFoam,
93  labelList& labels
94 )
95 {
96  forAll(labels, labelI)
97  {
98  labels[labelI] = mshToFoam[labels[labelI]];
99  }
100 }
101 
102 
103 // Find face in pp which uses all vertices in meshF (in mesh point labels)
104 label findFace(const primitivePatch& pp, const labelList& meshF)
105 {
106  const Map<label>& meshPointMap = pp.meshPointMap();
107 
108  // meshF[0] in pp labels.
109  if (!meshPointMap.found(meshF[0]))
110  {
111  Warning<< "Not using gmsh face " << meshF
112  << " since zero vertex is not on boundary of polyMesh" << endl;
113  return -1;
114  }
115 
116  // Find faces using first point
117  const labelList& pFaces = pp.pointFaces()[meshPointMap[meshF[0]]];
118 
119  // Go through all these faces and check if there is one which uses all of
120  // meshF vertices (in any order ;-)
121  forAll(pFaces, i)
122  {
123  label facei = pFaces[i];
124 
125  const face& f = pp[facei];
126 
127  // Count uses of vertices of meshF for f
128  label nMatched = 0;
129 
130  forAll(f, fp)
131  {
132  if (findIndex(meshF, f[fp]) != -1)
133  {
134  nMatched++;
135  }
136  }
137 
138  if (nMatched == meshF.size())
139  {
140  return facei;
141  }
142  }
143 
144  return -1;
145 }
146 
147 
148 // Same but find internal face. Expensive addressing.
149 label findInternalFace(const primitiveMesh& mesh, const labelList& meshF)
150 {
151  const labelList& pFaces = mesh.pointFaces()[meshF[0]];
152 
153  forAll(pFaces, i)
154  {
155  label facei = pFaces[i];
156 
157  const face& f = mesh.faces()[facei];
158 
159  // Count uses of vertices of meshF for f
160  label nMatched = 0;
161 
162  forAll(f, fp)
163  {
164  if (findIndex(meshF, f[fp]) != -1)
165  {
166  nMatched++;
167  }
168  }
169 
170  if (nMatched == meshF.size())
171  {
172  return facei;
173  }
174  }
175  return -1;
176 }
177 
178 
179 // Determine whether cell is inside-out by checking for any wrong-oriented
180 // face.
181 bool correctOrientation(const pointField& points, const cellShape& shape)
182 {
183  // Get centre of shape.
184  point cc(shape.centre(points));
185 
186  // Get outwards pointing faces.
187  faceList faces(shape.faces());
188 
189  forAll(faces, i)
190  {
191  const face& f = faces[i];
192 
193  const vector a(f.area(points));
194 
195  // Check if vector from any point on face to cc points outwards
196  if (((points[f[0]] - cc) & a) < 0)
197  {
198  // Incorrectly oriented
199  return false;
200  }
201  }
202 
203  return true;
204 }
205 
206 
207 void storeCellInZone
208 (
209  const label regPhys,
210  const label celli,
211  Map<label>& physToZone,
212 
213  labelList& zoneToPhys,
214  List<DynamicList<label>>& zoneCells
215 )
216 {
217  Map<label>::const_iterator zoneFnd = physToZone.find(regPhys);
218 
219  if (zoneFnd == physToZone.end())
220  {
221  // New region. Allocate zone for it.
222  label zoneI = zoneCells.size();
223  zoneCells.setSize(zoneI+1);
224  zoneToPhys.setSize(zoneI+1);
225 
226  Info<< "Mapping region " << regPhys << " to Foam cellZone "
227  << zoneI << endl;
228  physToZone.insert(regPhys, zoneI);
229 
230  zoneToPhys[zoneI] = regPhys;
231  zoneCells[zoneI].append(celli);
232  }
233  else
234  {
235  // Existing zone for region
236  zoneCells[zoneFnd()].append(celli);
237  }
238 }
239 
240 
241 // Reads mesh format
242 scalar readMeshFormat(IFstream& inFile)
243 {
244  Info<< "Starting to read mesh format at line "
245  << inFile.lineNumber()
246  << endl;
247 
248  string line;
249  inFile.getLine(line);
250  IStringStream lineStr(line);
251 
252  scalar version;
253  label asciiFlag, nBytes;
254  lineStr >> version >> asciiFlag >> nBytes;
255 
256  Info<< "Read format version " << version << " ascii " << asciiFlag << endl;
257 
258  if (asciiFlag != 0)
259  {
260  FatalIOErrorInFunction(inFile)
261  << "Can only read ascii msh files."
262  << exit(FatalIOError);
263  }
264 
265  inFile.getLine(line);
266  IStringStream tagStr(line);
267  variable tag(tagStr);
268 
269  if (tag != "$EndMeshFormat")
270  {
271  FatalIOErrorInFunction(inFile)
272  << "Did not find $ENDNOD tag on line "
273  << inFile.lineNumber() << exit(FatalIOError);
274  }
275  Info<< endl;
276 
277  return version;
278 }
279 
280 
281 // Reads points and map
282 void readPoints(IFstream& inFile, pointField& points, Map<label>& mshToFoam)
283 {
284  Info<< "Starting to read points at line " << inFile.lineNumber() << endl;
285 
286  string line;
287  inFile.getLine(line);
288  IStringStream lineStr(line);
289 
290  label nVerts;
291  lineStr >> nVerts;
292 
293  Info<< "Vertices to be read:" << nVerts << endl;
294 
295  points.setSize(nVerts);
296  mshToFoam.resize(2*nVerts);
297 
298  for (label pointi = 0; pointi < nVerts; pointi++)
299  {
300  label mshLabel;
301  scalar xVal, yVal, zVal;
302 
303  string line;
304  inFile.getLine(line);
305  IStringStream lineStr(line);
306 
307  lineStr >> mshLabel >> xVal >> yVal >> zVal;
308 
309  point& pt = points[pointi];
310 
311  pt.x() = xVal;
312  pt.y() = yVal;
313  pt.z() = zVal;
314 
315  mshToFoam.insert(mshLabel, pointi);
316  }
317 
318  Info<< "Vertices read:" << mshToFoam.size() << endl;
319 
320  inFile.getLine(line);
321  IStringStream tagStr(line);
322  variable tag(tagStr);
323 
324  if (tag != "$ENDNOD" && tag != "$EndNodes")
325  {
326  FatalIOErrorInFunction(inFile)
327  << "Did not find $ENDNOD tag on line "
328  << inFile.lineNumber() << exit(FatalIOError);
329  }
330  Info<< endl;
331 }
332 
333 
334 // Reads physical names
335 void readPhysNames(IFstream& inFile, Map<word>& physicalNames)
336 {
337  Info<< "Starting to read physical names at line " << inFile.lineNumber()
338  << endl;
339 
340  string line;
341  inFile.getLine(line);
342  IStringStream lineStr(line);
343 
344  label nNames;
345  lineStr >> nNames;
346 
347  Info<< "Physical names:" << nNames << endl;
348 
349  physicalNames.resize(nNames);
350 
351  for (label i = 0; i < nNames; i++)
352  {
353  label regionI;
354  string regionName;
355 
356  string line;
357  inFile.getLine(line);
358  IStringStream lineStr(line);
359  label nSpaces = lineStr.str().count(' ');
360 
361  if (nSpaces == 1)
362  {
363  lineStr >> regionI >> regionName;
364 
365  Info<< " " << regionI << '\t'
366  << string::validate<word>(regionName) << endl;
367  }
368  else if (nSpaces == 2)
369  {
370  // >= Gmsh2.4 physical types has tag in front.
371  label physType;
372  lineStr >> physType >> regionI >> regionName;
373  if (physType == 1)
374  {
375  Info<< " " << "Line " << regionI << '\t'
376  << string::validate<word>(regionName) << endl;
377  }
378  else if (physType == 2)
379  {
380  Info<< " " << "Surface " << regionI << '\t'
381  << string::validate<word>(regionName) << endl;
382  }
383  else if (physType == 3)
384  {
385  Info<< " " << "Volume " << regionI << '\t'
386  << string::validate<word>(regionName) << endl;
387  }
388  }
389 
390  physicalNames.insert(regionI, string::validate<word>(regionName));
391  }
392 
393  inFile.getLine(line);
394  IStringStream tagStr(line);
395  variable tag(tagStr);
396 
397  if (tag != "$EndPhysicalNames")
398  {
399  FatalIOErrorInFunction(inFile)
400  << "Did not find $EndPhysicalNames tag on line "
401  << inFile.lineNumber() << exit(FatalIOError);
402  }
403  Info<< endl;
404 }
405 
406 
407 // Reads cells and patch faces
408 void readCells
409 (
410  const scalar versionFormat,
411  const bool keepOrientation,
412  const pointField& points,
413  const Map<label>& mshToFoam,
414  IFstream& inFile,
416 
417  labelList& patchToPhys,
418  List<DynamicList<face>>& patchFaces,
419 
420  labelList& zoneToPhys,
421  List<DynamicList<label>>& zoneCells
422 )
423 {
424  Info<< "Starting to read cells at line " << inFile.lineNumber() << endl;
425 
426  const cellModel& hex = *(cellModeller::lookup("hex"));
427  const cellModel& prism = *(cellModeller::lookup("prism"));
428  const cellModel& pyr = *(cellModeller::lookup("pyr"));
429  const cellModel& tet = *(cellModeller::lookup("tet"));
430 
431  face triPoints(3);
432  face quadPoints(4);
433  labelList tetPoints(4);
434  labelList pyrPoints(5);
435  labelList prismPoints(6);
436  labelList hexPoints(8);
437 
438 
439  string line;
440  inFile.getLine(line);
441  IStringStream lineStr(line);
442 
443  label nElems;
444  lineStr >> nElems;
445 
446  Info<< "Cells to be read:" << nElems << endl << endl;
447 
448 
449  // Storage for all cells. Too big. Shrink later
450  cells.setSize(nElems);
451 
452  label celli = 0;
453  label nTet = 0;
454  label nPyr = 0;
455  label nPrism = 0;
456  label nHex = 0;
457 
458 
459  // From gmsh physical region to Foam patch
460  Map<label> physToPatch;
461 
462  // From gmsh physical region to Foam cellZone
463  Map<label> physToZone;
464 
465 
466  for (label elemI = 0; elemI < nElems; elemI++)
467  {
468  string line;
469  inFile.getLine(line);
470  IStringStream lineStr(line);
471 
472  label elmNumber, elmType, regPhys;
473 
474  if (versionFormat >= 2)
475  {
476  lineStr >> elmNumber >> elmType;
477 
478  label nTags;
479  lineStr>> nTags;
480 
481  if (nTags > 0)
482  {
483  // Assume the first tag is the physical surface
484  lineStr >> regPhys;
485  for (label i = 1; i < nTags; i++)
486  {
487  label dummy;
488  lineStr>> dummy;
489  }
490  }
491  }
492  else
493  {
494  label regElem, nNodes;
495  lineStr >> elmNumber >> elmType >> regPhys >> regElem >> nNodes;
496  }
497 
498  // regPhys on surface elements is region number.
499 
500  if (elmType == MSHTRI)
501  {
502  lineStr >> triPoints[0] >> triPoints[1] >> triPoints[2];
503 
504  renumber(mshToFoam, triPoints);
505 
506  Map<label>::iterator regFnd = physToPatch.find(regPhys);
507 
508  label patchi = -1;
509  if (regFnd == physToPatch.end())
510  {
511  // New region. Allocate patch for it.
512  patchi = patchFaces.size();
513 
514  patchFaces.setSize(patchi + 1);
515  patchToPhys.setSize(patchi + 1);
516 
517  Info<< "Mapping region " << regPhys << " to Foam patch "
518  << patchi << endl;
519  physToPatch.insert(regPhys, patchi);
520  patchToPhys[patchi] = regPhys;
521  }
522  else
523  {
524  // Existing patch for region
525  patchi = regFnd();
526  }
527 
528  // Add triangle to correct patchFaces.
529  patchFaces[patchi].append(triPoints);
530  }
531  else if (elmType == MSHQUAD)
532  {
533  lineStr
534  >> quadPoints[0] >> quadPoints[1] >> quadPoints[2]
535  >> quadPoints[3];
536 
537  renumber(mshToFoam, quadPoints);
538 
539  Map<label>::iterator regFnd = physToPatch.find(regPhys);
540 
541  label patchi = -1;
542  if (regFnd == physToPatch.end())
543  {
544  // New region. Allocate patch for it.
545  patchi = patchFaces.size();
546 
547  patchFaces.setSize(patchi + 1);
548  patchToPhys.setSize(patchi + 1);
549 
550  Info<< "Mapping region " << regPhys << " to Foam patch "
551  << patchi << endl;
552  physToPatch.insert(regPhys, patchi);
553  patchToPhys[patchi] = regPhys;
554  }
555  else
556  {
557  // Existing patch for region
558  patchi = regFnd();
559  }
560 
561  // Add quad to correct patchFaces.
562  patchFaces[patchi].append(quadPoints);
563  }
564  else if (elmType == MSHTET)
565  {
566  storeCellInZone
567  (
568  regPhys,
569  celli,
570  physToZone,
571  zoneToPhys,
572  zoneCells
573  );
574 
575  lineStr
576  >> tetPoints[0] >> tetPoints[1] >> tetPoints[2]
577  >> tetPoints[3];
578 
579  renumber(mshToFoam, tetPoints);
580 
581  cells[celli++] = cellShape(tet, tetPoints);
582 
583  nTet++;
584  }
585  else if (elmType == MSHPYR)
586  {
587  storeCellInZone
588  (
589  regPhys,
590  celli,
591  physToZone,
592  zoneToPhys,
593  zoneCells
594  );
595 
596  lineStr
597  >> pyrPoints[0] >> pyrPoints[1] >> pyrPoints[2]
598  >> pyrPoints[3] >> pyrPoints[4];
599 
600  renumber(mshToFoam, pyrPoints);
601 
602  cells[celli++] = cellShape(pyr, pyrPoints);
603 
604  nPyr++;
605  }
606  else if (elmType == MSHPRISM)
607  {
608  storeCellInZone
609  (
610  regPhys,
611  celli,
612  physToZone,
613  zoneToPhys,
614  zoneCells
615  );
616 
617  lineStr
618  >> prismPoints[0] >> prismPoints[1] >> prismPoints[2]
619  >> prismPoints[3] >> prismPoints[4] >> prismPoints[5];
620 
621  renumber(mshToFoam, prismPoints);
622 
623  cells[celli] = cellShape(prism, prismPoints);
624 
625  const cellShape& cell = cells[celli];
626 
627  if (!keepOrientation && !correctOrientation(points, cell))
628  {
629  Info<< "Inverting prism " << celli << endl;
630  // Reorder prism.
631  prismPoints[0] = cell[0];
632  prismPoints[1] = cell[2];
633  prismPoints[2] = cell[1];
634  prismPoints[3] = cell[3];
635  prismPoints[4] = cell[4];
636  prismPoints[5] = cell[5];
637 
638  cells[celli] = cellShape(prism, prismPoints);
639  }
640 
641  celli++;
642 
643  nPrism++;
644  }
645  else if (elmType == MSHHEX)
646  {
647  storeCellInZone
648  (
649  regPhys,
650  celli,
651  physToZone,
652  zoneToPhys,
653  zoneCells
654  );
655 
656  lineStr
657  >> hexPoints[0] >> hexPoints[1]
658  >> hexPoints[2] >> hexPoints[3]
659  >> hexPoints[4] >> hexPoints[5]
660  >> hexPoints[6] >> hexPoints[7];
661 
662  renumber(mshToFoam, hexPoints);
663 
664  cells[celli] = cellShape(hex, hexPoints);
665 
666  const cellShape& cell = cells[celli];
667 
668  if (!keepOrientation && !correctOrientation(points, cell))
669  {
670  Info<< "Inverting hex " << celli << endl;
671  // Reorder hex.
672  hexPoints[0] = cell[4];
673  hexPoints[1] = cell[5];
674  hexPoints[2] = cell[6];
675  hexPoints[3] = cell[7];
676  hexPoints[4] = cell[0];
677  hexPoints[5] = cell[1];
678  hexPoints[6] = cell[2];
679  hexPoints[7] = cell[3];
680 
681  cells[celli] = cellShape(hex, hexPoints);
682  }
683 
684  celli++;
685 
686  nHex++;
687  }
688  else
689  {
690  Info<< "Unhandled element " << elmType << " at line "
691  << inFile.lineNumber() << endl;
692  }
693  }
694 
695 
696  inFile.getLine(line);
697  IStringStream tagStr(line);
698  variable tag(tagStr);
699 
700  if (tag != "$ENDELM" && tag != "$EndElements")
701  {
702  FatalIOErrorInFunction(inFile)
703  << "Did not find $ENDELM tag on line "
704  << inFile.lineNumber() << exit(FatalIOError);
705  }
706 
707 
708  cells.setSize(celli);
709 
710  forAll(patchFaces, patchi)
711  {
712  patchFaces[patchi].shrink();
713  }
714 
715 
716  Info<< "Cells:" << endl
717  << " total:" << cells.size() << endl
718  << " hex :" << nHex << endl
719  << " prism:" << nPrism << endl
720  << " pyr :" << nPyr << endl
721  << " tet :" << nTet << endl
722  << endl;
723 
724  if (cells.size() == 0)
725  {
726  FatalIOErrorInFunction(inFile)
727  << "No cells read from file " << inFile.name() << nl
728  << "Does your file specify any 3D elements (hex=" << MSHHEX
729  << ", prism=" << MSHPRISM << ", pyramid=" << MSHPYR
730  << ", tet=" << MSHTET << ")?" << nl
731  << "Perhaps you have not exported the 3D elements?"
732  << exit(FatalIOError);
733  }
734 
735  Info<< "CellZones:" << nl
736  << "Zone\tSize" << endl;
737 
738  forAll(zoneCells, zoneI)
739  {
740  zoneCells[zoneI].shrink();
741 
742  const labelList& zCells = zoneCells[zoneI];
743 
744  if (zCells.size())
745  {
746  Info<< " " << zoneI << '\t' << zCells.size() << endl;
747  }
748  }
749  Info<< endl;
750 }
751 
752 
753 
754 int main(int argc, char *argv[])
755 {
757  argList::validArgs.append(".msh file");
759  (
760  "keepOrientation",
761  "retain raw orientation for prisms/hexs"
762  );
763 
764  #include "addMeshOption.H"
765  #include "addRegionOption.H"
766 
767  #include "setRootCase.H"
768  #include "setMeshPath.H"
769  #include "createTime.H"
770 
772 
773  if (args.optionReadIfPresent("region", regionName))
774  {
775  Foam::Info
776  << "Creating polyMesh for region " << regionName << endl;
777  }
778  else
779  {
781  }
782 
783  const bool keepOrientation = args.optionFound("keepOrientation");
784  IFstream inFile(args[1]);
785 
786  // Storage for points
788  Map<label> mshToFoam;
789 
790  // Storage for all cells.
792 
793  // Map from patch to gmsh physical region
794  labelList patchToPhys;
795  // Storage for patch faces.
796  List<DynamicList<face>> patchFaces(0);
797 
798  // Map from cellZone to gmsh physical region
799  labelList zoneToPhys;
800  // Storage for cell zones.
801  List<DynamicList<label>> zoneCells(0);
802 
803  // Name per physical region
804  Map<word> physicalNames;
805 
806  // Version 1 or 2 format
807  scalar versionFormat = 1;
808 
809 
810  while (inFile.good())
811  {
812  string line;
813  inFile.getLine(line);
814  IStringStream lineStr(line);
815 
816  variable tag(lineStr);
817 
818  if (tag == "$MeshFormat")
819  {
820  versionFormat = readMeshFormat(inFile);
821  }
822  else if (tag == "$PhysicalNames")
823  {
824  readPhysNames(inFile, physicalNames);
825  }
826  else if (tag == "$NOD" || tag == "$Nodes")
827  {
828  readPoints(inFile, points, mshToFoam);
829  }
830  else if (tag == "$ELM" || tag == "$Elements")
831  {
832  readCells
833  (
834  versionFormat,
835  keepOrientation,
836  points,
837  mshToFoam,
838  inFile,
839  cells,
840  patchToPhys,
841  patchFaces,
842  zoneToPhys,
843  zoneCells
844  );
845  }
846  else
847  {
848  Info<< "Skipping tag " << tag << " at line "
849  << inFile.lineNumber()
850  << endl;
851 
852  if (!skipSection(inFile))
853  {
854  break;
855  }
856  }
857  }
858 
859 
860  label nValidCellZones = 0;
861 
862  forAll(zoneCells, zoneI)
863  {
864  if (zoneCells[zoneI].size())
865  {
866  nValidCellZones++;
867  }
868  }
869 
870 
871  // Problem is that the orientation of the patchFaces does not have to
872  // be consistent with the outwards orientation of the mesh faces. So
873  // we have to construct the mesh in two stages:
874  // 1. define mesh with all boundary faces in one patch
875  // 2. use the read patchFaces to find the corresponding boundary face
876  // and repatch it.
877 
878 
879  // Create correct number of patches
880  // (but without any faces in it)
881  faceListList boundaryFaces(patchFaces.size());
882 
883  wordList boundaryPatchNames(boundaryFaces.size());
884 
885  forAll(boundaryPatchNames, patchi)
886  {
887  label physReg = patchToPhys[patchi];
888 
889  Map<word>::const_iterator iter = physicalNames.find(physReg);
890 
891  if (iter != physicalNames.end())
892  {
893  boundaryPatchNames[patchi] = iter();
894  }
895  else
896  {
897  boundaryPatchNames[patchi] = word("patch") + name(patchi);
898  }
899  Info<< "Patch " << patchi << " gets name "
900  << boundaryPatchNames[patchi] << endl;
901  }
902  Info<< endl;
903 
904  wordList boundaryPatchTypes(boundaryFaces.size(), polyPatch::typeName);
905  word defaultFacesName = "defaultFaces";
906  word defaultFacesType = polyPatch::typeName;
907  wordList boundaryPatchPhysicalTypes
908  (
909  boundaryFaces.size(),
910  polyPatch::typeName
911  );
912 
913  polyMesh mesh
914  (
915  IOobject
916  (
917  regionName,
918  runTime.constant(),
919  meshPath,
920  runTime
921  ),
922  move(points),
923  cells,
924  boundaryFaces,
925  boundaryPatchNames,
926  boundaryPatchTypes,
929  boundaryPatchPhysicalTypes
930  );
931 
933 
934  // Now use the patchFaces to patch up the outside faces of the mesh.
935 
936  // Get the patch for all the outside faces (= default patch added as last)
937  const polyPatch& pp = mesh.boundaryMesh().last();
938 
939  // Storage for faceZones.
940  List<DynamicList<label>> zoneFaces(patchFaces.size());
941 
942 
943  // Go through all the patchFaces and find corresponding face in pp.
944  forAll(patchFaces, patchi)
945  {
946  const DynamicList<face>& pFaces = patchFaces[patchi];
947 
948  Info<< "Finding faces of patch " << patchi << endl;
949 
950  forAll(pFaces, i)
951  {
952  const face& f = pFaces[i];
953 
954  // Find face in pp using all vertices of f.
955  label patchFacei = findFace(pp, f);
956 
957  if (patchFacei != -1)
958  {
959  label meshFacei = pp.start() + patchFacei;
960 
961  repatcher.changePatchID(meshFacei, patchi);
962  }
963  else
964  {
965  // Maybe internal face? If so add to faceZone with same index
966  // - might be useful.
967  label meshFacei = findInternalFace(mesh, f);
968 
969  if (meshFacei != -1)
970  {
971  zoneFaces[patchi].append(meshFacei);
972  }
973  else
974  {
976  << "Could not match gmsh face " << f
977  << " to any of the interior or exterior faces"
978  << " that share the same 0th point" << endl;
979  }
980  }
981  }
982  }
983  Info<< nl;
984 
985  // Face zones
986  label nValidFaceZones = 0;
987 
988  Info<< "FaceZones:" << nl
989  << "Zone\tSize" << endl;
990 
991  forAll(zoneFaces, zoneI)
992  {
993  zoneFaces[zoneI].shrink();
994 
995  const labelList& zFaces = zoneFaces[zoneI];
996 
997  if (zFaces.size())
998  {
999  nValidFaceZones++;
1000 
1001  Info<< " " << zoneI << '\t' << zFaces.size() << endl;
1002  }
1003  }
1004  Info<< endl;
1005 
1006 
1007  // Get polyMesh to write to constant
1008 
1009  runTime.setTime(instant(runTime.constant()), 0);
1010 
1011  repatcher.repatch();
1012 
1013  List<cellZone*> cz;
1014  List<faceZone*> fz;
1015 
1016  // Construct and add the zones. Note that cell ordering does not change
1017  // because of repatch() and neither does internal faces so we can
1018  // use the zoneCells/zoneFaces as is.
1019 
1020  if (nValidCellZones > 0)
1021  {
1022  cz.setSize(nValidCellZones);
1023 
1024  nValidCellZones = 0;
1025 
1026  forAll(zoneCells, zoneI)
1027  {
1028  if (zoneCells[zoneI].size())
1029  {
1030  label physReg = zoneToPhys[zoneI];
1031 
1032  Map<word>::const_iterator iter = physicalNames.find(physReg);
1033 
1034  word zoneName = "cellZone_" + name(zoneI);
1035  if (iter != physicalNames.end())
1036  {
1037  zoneName = iter();
1038  }
1039 
1040  Info<< "Writing zone " << zoneI << " to cellZone "
1041  << zoneName << " and cellSet"
1042  << endl;
1043 
1044  cellSet cset(mesh, zoneName, zoneCells[zoneI]);
1045  cset.write();
1046 
1047  cz[nValidCellZones] = new cellZone
1048  (
1049  zoneName,
1050  zoneCells[zoneI],
1051  mesh.cellZones()
1052  );
1053  nValidCellZones++;
1054  }
1055  }
1056  }
1057 
1058  if (nValidFaceZones > 0)
1059  {
1060  fz.setSize(nValidFaceZones);
1061 
1062  nValidFaceZones = 0;
1063 
1064  forAll(zoneFaces, zoneI)
1065  {
1066  if (zoneFaces[zoneI].size())
1067  {
1068  label physReg = patchToPhys[zoneI];
1069 
1070  Map<word>::const_iterator iter = physicalNames.find(physReg);
1071 
1072  word zoneName = "faceZone_" + name(zoneI);
1073  if (iter != physicalNames.end())
1074  {
1075  zoneName = iter();
1076  }
1077 
1078  Info<< "Writing zone " << zoneI << " to faceZone "
1079  << zoneName << " and faceSet"
1080  << endl;
1081 
1082  faceSet fset(mesh, zoneName, zoneFaces[zoneI]);
1083  fset.write();
1084 
1085  fz[nValidFaceZones] = new faceZone
1086  (
1087  zoneName,
1088  zoneFaces[zoneI],
1089  boolList(zoneFaces[zoneI].size(), true),
1090  mesh.faceZones()
1091  );
1092  nValidFaceZones++;
1093  }
1094  }
1095  }
1096 
1097  if (cz.size() || fz.size())
1098  {
1099  mesh.addZones(List<pointZone*>(0), fz, cz);
1100  }
1101 
1102  // Remove empty defaultFaces
1103  label defaultPatchID = mesh.boundaryMesh().findIndex(defaultFacesName);
1104  if (mesh.boundaryMesh()[defaultPatchID].size() == 0)
1105  {
1106  List<polyPatch*> newPatchPtrList((mesh.boundaryMesh().size() - 1));
1107  label newPatchi = 0;
1109  {
1110  if (patchi != defaultPatchID)
1111  {
1112  const polyPatch& patch = mesh.boundaryMesh()[patchi];
1113 
1114  newPatchPtrList[newPatchi] = patch.clone
1115  (
1116  mesh.boundaryMesh(),
1117  newPatchi,
1118  patch.size(),
1119  patch.start()
1120  ).ptr();
1121 
1122  newPatchi++;
1123  }
1124  }
1125  repatcher.changePatches(newPatchPtrList);
1126  }
1127 
1128  mesh.write();
1129 
1130  Info<< "End\n" << endl;
1131 
1132  return 0;
1133 }
1134 
1135 
1136 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:167
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:138
void resize(const label newSize)
Resize the hash table for efficiency.
Definition: HashTable.C:506
Input from file stream.
Definition: IFstream.H:85
const fileName & name() const
Return the name of the stream.
Definition: IFstream.H:116
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
label lineNumber() const
Return current stream line number.
Definition: IOstream.H:450
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:333
ISstream & getLine(string &, const bool continuation=true)
Read line into a string.
Definition: ISstream.C:703
Input from memory buffer stream.
Definition: IStringStream.H:52
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
const Map< label > & meshPointMap() const
Mesh point map. Given the global point index find its.
const labelListList & pointFaces() const
Return point-face addressing.
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
T & last()
Return reference to the last element of the list.
Definition: UPtrListI.H:57
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:118
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:114
bool optionReadIfPresent(const word &opt, T &) const
Read a value from the named option if present.
Definition: argListI.H:255
static void noParallel()
Remove the parallel options.
Definition: argList.C:175
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:153
Maps a geometry to a set of cell primitives, which enables geometric cell data to be calculated witho...
Definition: cellModel.H:65
static const cellModel * lookup(const word &)
Look up a model by name and return a pointer to the model or nullptr.
Definition: cellModeller.C:100
A collection of cell labels.
Definition: cellSet.H:51
An analytical geometric cellShape.
Definition: cellShape.H:72
point centre(const pointField &) const
Centroid of the cell.
Definition: cellShapeI.H:259
faceList faces() const
Faces of this cell.
Definition: cellShapeI.H:180
Named list of cell indices representing a sub-set of the mesh.
Definition: cellZone.H:61
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:60
A list of face labels.
Definition: faceSet.H:51
Named list of face indices representing a sub-set of the mesh faces.
Definition: faceZone.H:66
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
virtual bool write(const bool write=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:1785
An instant of time. Contains the time value and name.
Definition: instant.H:67
A line primitive.
Definition: line.H:71
label findIndex(const word &patchName) const
Find patch index given a name.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
const cellZoneList & cellZones() const
Return cell zones.
Definition: polyMesh.H:449
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:270
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1344
const faceZoneList & faceZones() const
Return face zones.
Definition: polyMesh.H:443
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:401
void addZones(const List< pointZone * > &pz, const List< faceZone * > &fz, const List< cellZone * > &cz)
Add mesh zones.
Definition: polyMesh.C:1145
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:70
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:280
virtual autoPtr< polyPatch > clone(const polyBoundaryMesh &bm) const
Construct and return a clone, resetting the boundary mesh.
Definition: polyPatch.H:215
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:75
const labelListList & pointFaces() const
A mesh which allows changes in the patch distribution of the boundary faces. The change in patching i...
Definition: repatcher.H:53
void changePatchID(const label faceID, const label patchID)
Change patch ID for a boundary face. Note: patchID should be in new.
Definition: repatcher.C:83
void changePatches(const List< polyPatch * > &patches)
Change patches.
Definition: repatcher.C:66
void repatch()
Re-patch the mesh.
Definition: repatcher.C:190
A variable is a word with support for additional characters, in particular '$' and '/'.
Definition: variable.H:61
A class for handling words, derived from string.
Definition: word.H:62
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
int main(int argc, char *argv[])
Definition: financialFoam.C:44
label patchi
const pointField & points
const cellShapeList & cells
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
static const labelSphericalTensor labelI(1)
Identity labelTensor.
const word & regionName(const solver &region)
Definition: solver.H:218
ListType renumber(const labelUList &oldToNew, const ListType &)
Renumber the values (not the indices) of a list.
IOstream & hex(IOstream &io)
Definition: IOstream.H:576
messageStream Info
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
IOerror FatalIOError
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
static const char nl
Definition: Ostream.H:267
messageStream Warning
labelList f(nPoints)
word defaultFacesName
Definition: readKivaGrid.H:454
word defaultFacesType
Definition: readKivaGrid.H:455
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("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]=cellShape(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, &mergedCyclicPolyPatch::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:229
word meshPath
Definition: setMeshPath.H:1
Foam::argList args(argc, argv)
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:112