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