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-------------------------------------------------------------------------------
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
101void 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)
115label 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.
160label 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.
192bool 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
216void 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
251scalar 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 {
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 {
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
291void 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 {
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
342void 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 {
405 << "Did not find $ENDNOD tag on line "
406 << inFile.lineNumber() << exit(FatalIOError);
407 }
408 Info<< endl;
409}
410
411
412// Reads physical names
413void 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'
442 << word::validate(regionName) << endl;
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'
452 << word::validate(regionName) << endl;
453 }
454 else if (physType == 2)
455 {
456 Info<< " " << "Surface " << regionI << '\t'
457 << word::validate(regionName) << endl;
458 }
459 else if (physType == 3)
460 {
461 Info<< " " << "Volume " << regionI << '\t'
462 << word::validate(regionName) << endl;
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 {
480 << "Did not find $EndPhysicalNames tag on line "
481 << inFile.lineNumber() << exit(FatalIOError);
482 }
483 Info<< endl;
484}
485
486void 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
509 const cellModel& hex = cellModel::ref(cellModel::HEX);
510 const cellModel& prism = cellModel::ref(cellModel::PRISM);
511 const cellModel& pyr = cellModel::ref(cellModel::PYR);
512 const cellModel& tet = cellModel::ref(cellModel::TET);
513
514 face triPoints(3);
515 face quadPoints(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 {
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 {
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
838void 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
858 const cellModel& hex = cellModel::ref(cellModel::HEX);
859 const cellModel& prism = cellModel::ref(cellModel::PRISM);
860 const cellModel& pyr = cellModel::ref(cellModel::PYR);
861 const cellModel& tet = cellModel::ref(cellModel::TET);
862
863 face triPoints(3);
864 face quadPoints(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 {
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 {
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
1212void 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 {
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 {
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 {
1294 << "Did not find $EndEntities tag on line "
1295 << inFile.lineNumber() << exit(FatalIOError);
1296 }
1297}
1298
1299
1300int main(int argc, char *argv[])
1301{
1302 argList::addNote
1303 (
1304 "Convert a gmsh .msh file to OpenFOAM"
1305 );
1306
1307 argList::noParallel();
1308 argList::addArgument(".msh file");
1309 argList::addBoolOption
1310 (
1311 "keepOrientation",
1312 "Retain raw orientation for prisms/hexs"
1313 );
1314
1315 #include "addRegionOption.H"
1316
1317 #include "setRootCase.H"
1318 #include "createTime.H"
1319
1320 word regionName(polyMesh::defaultRegion);
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
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
1584 runTime.setTime(instant(runTime.constant()), 0);
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
1704 IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
1705
1706 mesh.write();
1707
1708 Info<< "End\n" << endl;
1709
1710 return 0;
1711}
1712
1713
1714// ************************************************************************* //
Y[inertIndex] max(0.0)
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
const T & lookup(const Key &key, const T &deflt) const
Return hashed entry if it exists, or return the given default.
Definition: HashTableI.H:224
bool found(const Key &key) const
Return true if hashed entry is found in table.
Definition: HashTableI.H:100
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition: HashTableI.H:141
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:180
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
Input from file stream, using an ISstream.
Definition: IFstream.H:57
virtual const fileName & name() const
Read/write access to the name of the stream.
Definition: ISstream.H:113
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
label lineNumber() const noexcept
Const access to the current stream line number.
Definition: IOstream.H:318
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:233
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition: ISstreamI.H:76
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Definition: StringStream.H:112
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
A HashTable to objects of type <T> with a label key.
Definition: Map.H:60
A list of faces which address into the list of points.
const Map< label > & meshPointMap() const
Mesh point map.
const labelListList & pointFaces() const
Return point-face addressing.
bool found(const T &val, label pos=0) const
True if the value if found in the list.
Definition: UListI.H:265
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:278
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:178
bool readIfPresent(const word &optName, T &val) const
Read a value from the named option if present.
Definition: argListI.H:323
Maps a geometry to a set of cell primitives.
Definition: cellModel.H:73
A collection of cell labels.
Definition: cellSet.H:54
An analytical geometric cellShape.
Definition: cellShape.H:72
point centre(const UList< point > &points) const
Centroid of the cell.
Definition: cellShapeI.H:287
faceList faces() const
Faces of this cell.
Definition: cellShapeI.H:227
A subset of mesh cells.
Definition: cellZone.H:65
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:57
A list of face labels.
Definition: faceSet.H:54
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:67
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
A class for handling file names.
Definition: fileName.H:76
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:68
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:364
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:79
A mesh which allows changes in the patch distribution of the boundary faces. The change in patching i...
Tet storage. Null constructable (unfortunately tetrahedron<point, point> is not)
Definition: tetPoints.H:56
Triangle storage. Null constructable (unfortunately triangle<point, point> is not)
Definition: triPoints.H:55
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:68
const cellModel & hex
dynamicFvMesh & mesh
engineTime & runTime
Foam::word regionName(Foam::polyMesh::defaultRegion)
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
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.
messageStream Info
Information stream (stdout output on master, null elsewhere)
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
messageStream Warning
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
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
labelList f(nPoints)
word defaultFacesName
Definition: readKivaGrid.H:455
word defaultFacesType
Definition: readKivaGrid.H:456
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333