Loading...
Searching...
No Matches
ideasUnvToFoam.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-2017 OpenFOAM Foundation
9 Copyright (C) 2021-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 ideasUnvToFoam
29
30Group
31 grpMeshConversionUtilities
32
33Description
34 I-Deas unv format mesh conversion.
35
36 Uses either
37 - DOF sets (757) or
38 - face groups (2452(Cubit), 2467)
39 to do patching.
40 Works without but then puts all faces in defaultFaces patch.
41
42\*---------------------------------------------------------------------------*/
43
44#include "argList.H"
45#include "polyMesh.H"
46#include "Time.H"
47#include "IFstream.H"
48#include "cellModel.H"
49#include "cellSet.H"
50#include "faceSet.H"
51#include "DynamicList.H"
52
53#include <cassert>
54#include "MeshedSurfaces.H"
55
56using namespace Foam;
57
58// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
59
60const string SEPARATOR(" -1");
61
62bool isSeparator(const std::string& line)
63{
64 return line.substr(0, 6) == SEPARATOR;
65}
66
67
68// Reads past -1 and reads element type
69label readTag(IFstream& is)
70{
71 string tag;
72 do
73 {
74 if (!is.good())
75 {
76 return -1;
77 }
78
79 string line;
80
81 is.getLine(line);
82
83 if (line.size() < 6)
84 {
85 return -1;
86 }
87
88 tag = line.substr(0, 6);
89
90 } while (tag == SEPARATOR);
91
92 return readLabel(tag);
93}
94
95
96// Reads and prints header
97void readHeader(IFstream& is)
98{
99 string line;
100
101 while (is.good())
102 {
103 is.getLine(line);
104
105 if (isSeparator(line))
106 {
107 break;
108 }
109 else
110 {
111 Info<< line << endl;
112 }
113 }
114}
115
116
117// Skip
118void skipSection(IFstream& is)
119{
120 Info<< "Skipping section at line " << is.lineNumber() << '.' << endl;
121
122 string line;
123
124 while (is.good())
125 {
126 is.getLine(line);
127
128 if (isSeparator(line))
129 {
130 break;
131 }
132 }
133}
134
135
136scalar readUnvScalar(const std::string& unvString)
137{
138 string s(unvString);
139
140 s.replaceAll("d", "E");
141 s.replaceAll("D", "E");
142
143 return readScalar(s);
144}
145
146
147// Reads unit section
148void readUnits
149(
150 IFstream& is,
151 scalar& lengthScale,
152 scalar& forceScale,
153 scalar& tempScale,
154 scalar& tempOffset
155)
156{
157 Info<< "Starting reading units at line " << is.lineNumber() << '.' << endl;
158
159 string line;
160 is.getLine(line);
161
162 label l = readLabel(line.substr(0, 10));
163 Info<< "l:" << l << endl;
164
165 string units(line.substr(10, 20));
166 Info<< "units:" << units << endl;
167
168 label unitType = readLabel(line.substr(30, 10));
169 Info<< "unitType:" << unitType << endl;
170
171 // Read lengthscales
172 is.getLine(line);
173
174 lengthScale = readUnvScalar(line.substr(0, 25));
175 forceScale = readUnvScalar(line.substr(25, 25));
176 tempScale = readUnvScalar(line.substr(50, 25));
177
178 is.getLine(line);
179 tempOffset = readUnvScalar(line.substr(0, 25));
180
181 Info<< "Unit factors:" << nl
182 << " Length scale : " << lengthScale << nl
183 << " Force scale : " << forceScale << nl
184 << " Temperature scale : " << tempScale << nl
185 << " Temperature offset : " << tempOffset << nl
186 << endl;
187}
188
189
190// Reads points section. Read region as well?
191void readPoints
192(
193 IFstream& is,
194 DynamicList<point>& points, // coordinates
195 DynamicList<label>& unvPointID // unv index
196)
197{
198 Info<< "Starting reading points at line " << is.lineNumber() << '.' << endl;
199
200 static bool hasWarned = false;
201
202 while (true)
203 {
204 string line;
205 is.getLine(line);
206
207 label pointi = readLabel(line.substr(0, 10));
208
209 if (pointi == -1)
210 {
211 break;
212 }
213 else if (pointi != points.size()+1 && !hasWarned)
214 {
215 hasWarned = true;
216
218 << "Points not in order starting at point " << pointi
219 << endl;
220 }
221
222 is.getLine(line);
223
224 unvPointID.push_back(pointi);
225 point& p = points.emplace_back();
226
227 p.x() = readUnvScalar(line.substr(0, 25));
228 p.y() = readUnvScalar(line.substr(25, 25));
229 p.z() = readUnvScalar(line.substr(50, 25));
230 }
231
232 points.shrink();
233 unvPointID.shrink();
234
235 Info<< "Read " << points.size() << " points." << endl;
236}
237
238void addAndExtend
239(
240 DynamicList<label>& indizes,
241 label celli,
242 label val
243)
244{
245 if (indizes.size() < (celli+1))
246 {
247 indizes.setSize(celli+1,-1);
248 }
249 indizes[celli] = val;
250}
251
252// Reads cells section. Read region as well? Not handled yet but should just
253// be a matter of reading corresponding to boundaryFaces the correct property
254// and sorting it later on.
255void readCells
256(
257 IFstream& is,
258 DynamicList<cellShape>& cellVerts,
259 DynamicList<label>& cellMaterial,
260 DynamicList<label>& boundaryFaceIndices,
261 DynamicList<face>& boundaryFaces,
262 DynamicList<label>& cellCorrespondence,
263 DynamicList<label>& unvPointID // unv index
264)
265{
266 Info<< "Starting reading cells at line " << is.lineNumber() << '.' << endl;
267
268 // Invert point numbering.
269 label maxUnvPoint = 0;
270 forAll(unvPointID, pointi)
271 {
272 maxUnvPoint = Foam::max(maxUnvPoint, unvPointID[pointi]);
273 }
274 labelList unvToFoam(invert(maxUnvPoint+1, unvPointID));
275
276
280
281 labelHashSet skippedElements;
282
283 labelHashSet foundFeType;
284
285 while (true)
286 {
287 string line;
288 is.getLine(line);
289
290 if (isSeparator(line))
291 {
292 break;
293 }
294
295 label celli, feID, physProp, matProp, colour, nNodes;
296
297 IStringStream lineStr(line);
298 lineStr
299 >> celli >> feID >> physProp >> matProp >> colour >> nNodes;
300
301 if (foundFeType.insert(feID))
302 {
303 Info<< "First occurrence of element type " << feID
304 << " for cell " << celli << " at line "
305 << is.lineNumber() << endl;
306 }
307
308 if (feID == 11)
309 {
310 // Rod. Skip.
311 is.getLine(line);
312 is.getLine(line);
313 }
314 else if (feID == 171)
315 {
316 // Rod. Skip.
317 is.getLine(line);
318 }
319 else if (feID == 41 || feID == 91)
320 {
321 // Triangle. Save - used for patching later on.
322 is.getLine(line);
323
324 face cVerts(3);
325 IStringStream lineStr(line);
326 lineStr
327 >> cVerts[0] >> cVerts[1] >> cVerts[2];
328 boundaryFaces.append(cVerts);
329 boundaryFaceIndices.append(celli);
330 }
331 else if (feID == 44 || feID == 94)
332 {
333 // Quad. Save - used for patching later on.
334 is.getLine(line);
335
336 face cVerts(4);
337 IStringStream lineStr(line);
338 lineStr
339 >> cVerts[0] >> cVerts[1] >> cVerts[2] >> cVerts[3];
340 boundaryFaces.append(cVerts);
341 boundaryFaceIndices.append(celli);
342 }
343 else if (feID == 111)
344 {
345 // Tet.
346 is.getLine(line);
347
348 labelList cVerts(4);
349 IStringStream lineStr(line);
350 lineStr
351 >> cVerts[0] >> cVerts[1] >> cVerts[2] >> cVerts[3];
352
353 cellVerts.append(cellShape(tet, cVerts, true));
354 cellMaterial.append(physProp);
355 addAndExtend(cellCorrespondence,celli,cellMaterial.size()-1);
356
357 if (cellVerts.last().size() != cVerts.size())
358 {
359 Info<< "Line:" << is.lineNumber()
360 << " element:" << celli
361 << " type:" << feID
362 << " collapsed from " << cVerts << nl
363 << " to:" << cellVerts.last()
364 << endl;
365 }
366 }
367 else if (feID == 112)
368 {
369 // Wedge.
370 is.getLine(line);
371
372 labelList cVerts(6);
373 IStringStream lineStr(line);
374 lineStr
375 >> cVerts[0] >> cVerts[1] >> cVerts[2]
376 >> cVerts[3] >> cVerts[4] >> cVerts[5];
377
378 cellVerts.append(cellShape(prism, cVerts, true));
379 cellMaterial.append(physProp);
380 addAndExtend(cellCorrespondence,celli,cellMaterial.size()-1);
381
382 if (cellVerts.last().size() != cVerts.size())
383 {
384 Info<< "Line:" << is.lineNumber()
385 << " element:" << celli
386 << " type:" << feID
387 << " collapsed from " << cVerts << nl
388 << " to:" << cellVerts.last()
389 << endl;
390 }
391 }
392 else if (feID == 115)
393 {
394 // Hex.
395 is.getLine(line);
396
397 labelList cVerts(8);
398 IStringStream lineStr(line);
399 lineStr
400 >> cVerts[0] >> cVerts[1] >> cVerts[2] >> cVerts[3]
401 >> cVerts[4] >> cVerts[5] >> cVerts[6] >> cVerts[7];
402
403 cellVerts.append(cellShape(hex, cVerts, true));
404 cellMaterial.append(physProp);
405 addAndExtend(cellCorrespondence,celli,cellMaterial.size()-1);
406
407 if (cellVerts.last().size() != cVerts.size())
408 {
409 Info<< "Line:" << is.lineNumber()
410 << " element:" << celli
411 << " type:" << feID
412 << " collapsed from " << cVerts << nl
413 << " to:" << cellVerts.last()
414 << endl;
415 }
416 }
417 else if (feID == 118)
418 {
419 // Parabolic Tet
420 is.getLine(line);
421
422 labelList cVerts(4);
423 label dummy;
424 {
425 IStringStream lineStr(line);
426 lineStr
427 >> cVerts[0] >> dummy >> cVerts[1] >> dummy >> cVerts[2];
428 }
429 is.getLine(line);
430 {
431 IStringStream lineStr(line);
432 lineStr >> dummy>> cVerts[3];
433 }
434
435 cellVerts.append(cellShape(tet, cVerts, true));
436 cellMaterial.append(physProp);
437 addAndExtend(cellCorrespondence,celli,cellMaterial.size()-1);
438
439 if (cellVerts.last().size() != cVerts.size())
440 {
441 Info<< "Line:" << is.lineNumber()
442 << " element:" << celli
443 << " type:" << feID
444 << " collapsed from " << cVerts << nl
445 << " to:" << cellVerts.last()
446 << endl;
447 }
448 }
449 else
450 {
451 if (skippedElements.insert(feID))
452 {
454 << "Cell type " << feID << " not supported" << endl;
455 }
456
457 is.getLine(line);
458 }
459 }
460
461 cellVerts.shrink();
462 cellMaterial.shrink();
463 boundaryFaces.shrink();
464 boundaryFaceIndices.shrink();
465 cellCorrespondence.shrink();
466
467 Info<< "Read " << cellVerts.size() << " cells"
468 << " and " << boundaryFaces.size() << " boundary faces." << endl;
469
470 if (!cellVerts.size())
471 {
473 << "There are no cells in the mesh." << endl
474 << " Note: 2D meshes are not supported."<< endl;
475 }
476}
477
478
479void readSets
480(
481 IFstream& is,
483 DynamicList<labelList>& patchFaceIndices
484)
485{
486 Info<< "Starting reading patches at line " << is.lineNumber() << '.'
487 << endl;
488
489 while (true)
490 {
491 string line;
492 is.getLine(line);
493
494 if (isSeparator(line))
495 {
496 break;
497 }
498
499 IStringStream lineStr(line);
500 label group, constraintSet, restraintSet, loadSet, dofSet,
501 tempSet, contactSet, nFaces;
502 lineStr
503 >> group >> constraintSet >> restraintSet >> loadSet
504 >> dofSet >> tempSet >> contactSet >> nFaces;
505
506 is.getLine(line);
507 const word groupName = word::validate(line);
508
509 Info<< "For group " << group
510 << " named " << groupName
511 << " trying to read " << nFaces << " patch face indices."
512 << endl;
513
514 labelList groupIndices(nFaces);
515 label groupType = -1;
516 nFaces = 0;
517
518 while (nFaces < groupIndices.size())
519 {
520 is.getLine(line);
521 IStringStream lineStr(line);
522
523 // Read one (for last face) or two entries from line.
524 label nRead = 2;
525 if (nFaces == groupIndices.size()-1)
526 {
527 nRead = 1;
528 }
529
530 for (label i = 0; i < nRead; i++)
531 {
532 label tag, nodeLeaf, component;
533
534 lineStr >> groupType >> tag >> nodeLeaf >> component;
535
536 groupIndices[nFaces++] = tag;
537 }
538 }
539
540
541 // Store
542 if (groupType == 8)
543 {
544 patchNames.append(groupName);
545 patchFaceIndices.append(groupIndices);
546 }
547 else
548 {
550 << "When reading patches expect entity type code 8"
551 << nl << " Skipping group code " << groupType
552 << endl;
553 }
554 }
555
556 patchNames.shrink();
557 patchFaceIndices.shrink();
558}
559
560
561
562// Read dof set (757)
563void readDOFS
564(
565 IFstream& is,
567 DynamicList<labelList>& dofVertices
568)
569{
570 Info<< "Starting reading constraints at line " << is.lineNumber() << '.'
571 << endl;
572
573 string line;
574 is.getLine(line);
575 label group;
576 {
577 IStringStream lineStr(line);
578 lineStr >> group;
579 }
580
581 is.getLine(line);
582 {
583 IStringStream lineStr(line);
584 word pName(lineStr);
585 patchNames.append(pName);
586 }
587
588 Info<< "For DOF set " << group
589 << " named " << patchNames.last()
590 << " trying to read vertex indices."
591 << endl;
592
594 while (true)
595 {
596 string line;
597 is.getLine(line);
598
599 if (isSeparator(line))
600 {
601 break;
602 }
603
604 IStringStream lineStr(line);
605 label pointi;
606 lineStr >> pointi;
607
608 vertices.append(pointi);
609 }
610
611 Info<< "For DOF set " << group
612 << " named " << patchNames.last()
613 << " read " << vertices.size() << " vertex indices." << endl;
614
615 dofVertices.append(vertices.shrink());
616
617 patchNames.shrink();
618 dofVertices.shrink();
619}
620
621
622// Returns -1 or group that all of the vertices of f are in,
623label findPatch(const List<labelHashSet>& dofGroups, const face& f)
624{
625 forAll(dofGroups, patchi)
626 {
627 if (dofGroups[patchi].found(f[0]))
628 {
629 bool allInGroup = true;
630
631 // Check rest of face
632 for (label fp = 1; fp < f.size(); fp++)
633 {
634 if (!dofGroups[patchi].found(f[fp]))
635 {
636 allInGroup = false;
637 break;
638 }
639 }
640
641 if (allInGroup)
642 {
643 return patchi;
644 }
645 }
646 }
647 return -1;
648}
649
650
651
652int main(int argc, char *argv[])
653{
655 (
656 "Convert I-Deas unv format to OpenFOAM"
657 );
659 argList::addArgument(".unv file");
661 (
662 "dump",
663 "Dump boundary faces as boundaryFaces.obj (for debugging)"
664 );
665
666 #include "setRootCase.H"
667 #include "createTime.H"
668
669 const auto ideasName = args.get<fileName>(1);
670 IFstream inFile(ideasName);
671
672 if (!inFile.good())
673 {
675 << "Cannot open file " << ideasName
676 << exit(FatalError);
677 }
678
679
680 // Switch on additional debug info
681 const bool verbose = false; //true;
682
683 // Unit scale factors
684 scalar lengthScale = 1;
685 scalar forceScale = 1;
686 scalar tempScale = 1;
687 scalar tempOffset = 0;
688
689 // Points
691 // Original unv point label
692 DynamicList<label> unvPointID;
693
694 // Cells
695 DynamicList<cellShape> cellVerts;
696 DynamicList<label> cellMat;
697 DynamicList<label> cellCorrespondence;
698
699 // Boundary faces
700 DynamicList<label> boundaryFaceIndices;
701 DynamicList<face> boundaryFaces;
702
703 // Patch names and patchFace indices.
705 DynamicList<labelList> patchFaceIndices;
706 DynamicList<labelList> dofVertIndices;
707
708
709 while (inFile.good())
710 {
711 label tag = readTag(inFile);
712
713 if (tag == -1)
714 {
715 break;
716 }
717
718 Info<< "Processing tag:" << tag << endl;
719
720 switch (tag)
721 {
722 case 151:
723 readHeader(inFile);
724 break;
725
726 case 164:
727 readUnits
728 (
729 inFile,
730 lengthScale,
731 forceScale,
732 tempScale,
733 tempOffset
734 );
735 break;
736
737 case 2411:
738 readPoints(inFile, points, unvPointID);
739 break;
740
741 case 2412:
742 readCells
743 (
744 inFile,
745 cellVerts,
746 cellMat,
747 boundaryFaceIndices,
748 boundaryFaces,
749 cellCorrespondence,
750 unvPointID
751 );
752 break;
753
754 case 2452:
755 case 2467:
756 readSets
757 (
758 inFile,
760 patchFaceIndices
761 );
762 break;
763
764 case 757:
765 readDOFS
766 (
767 inFile,
769 dofVertIndices
770 );
771 break;
772
773 default:
774 Info<< "Skipping tag " << tag << " on line "
775 << inFile.lineNumber() << endl;
776 skipSection(inFile);
777 break;
778 }
779 Info<< endl;
780 }
781
782
783 // Invert point numbering.
784 label maxUnvPoint = 0;
785 forAll(unvPointID, pointi)
786 {
787 maxUnvPoint = Foam::max(maxUnvPoint, unvPointID[pointi]);
788 }
789 labelList unvToFoam(invert(maxUnvPoint+1, unvPointID));
790
791
792 // Renumber vertex numbers on cells
793
794 forAll(cellVerts, celli)
795 {
796 labelList foamVerts
797 (
799 (
800 unvToFoam,
801 static_cast<labelList&>(cellVerts[celli])
802 )
803 );
804
805 if (foamVerts.found(-1))
806 {
808 << "Cell " << celli
809 << " unv vertices " << cellVerts[celli]
810 << " has some undefined vertices " << foamVerts
811 << abort(FatalError);
812 }
813
814 // Bit nasty: replace vertex list.
815 cellVerts[celli].transfer(foamVerts);
816 }
817
818 // Renumber vertex numbers on boundaryFaces
819
820 forAll(boundaryFaces, bFacei)
821 {
822 labelList foamVerts(renumber(unvToFoam, boundaryFaces[bFacei]));
823
824 if (foamVerts.found(-1))
825 {
827 << "Boundary face " << bFacei
828 << " unv vertices " << boundaryFaces[bFacei]
829 << " has some undefined vertices " << foamVerts
830 << abort(FatalError);
831 }
832
833 // Bit nasty: replace vertex list.
834 boundaryFaces[bFacei].transfer(foamVerts);
835 }
836
837
838
839 // Patchify = create patchFaceVerts for use in cellShape construction
840 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
841
842 // Works in one of two modes. Either has read boundaryFaces which
843 // just need to be sorted according to patch. Or has read point constraint
844 // sets (dofVertIndices).
845
846 List<faceList> patchFaceVerts;
847
848 labelList own(boundaryFaces.size(), -1);
849 labelList nei(boundaryFaces.size(), -1);
850 Pair<Map<label>> faceToCell;
851
852 {
853 // Can use face::symmHasher or use sorted indices instead
854 // - choose the latter in case UNV has anything odd
855 HashTable<label, face> faceToFaceID(2*boundaryFaces.size());
856
857 forAll(boundaryFaces, bfacei)
858 {
859 face sortedVerts(boundaryFaces[bfacei]);
860 Foam::sort(sortedVerts);
861 faceToFaceID.insert(sortedVerts, bfacei);
862 }
863
864 forAll(cellVerts, celli)
865 {
866 const cellShape& shape = cellVerts[celli];
867
868 for (const face& f : shape.faces())
869 {
870 face sortedVerts(f);
871 Foam::sort(sortedVerts);
872 const label bfacei = faceToFaceID.lookup(sortedVerts, -1);
873 if (bfacei != -1)
874 {
875 const int cmp = face::compare(f, boundaryFaces[bfacei]);
876
877 if (cmp == 1)
878 {
879 // Same orientation. Cell is owner.
880 own[bfacei] = celli;
881 }
882 else if (cmp == -1)
883 {
884 // Opposite orientation. Cell is neighbour.
885 nei[bfacei] = celli;
886 }
887 }
888 }
889 }
890
891 label nReverse = 0;
892 forAll(own, facei)
893 {
894 if (own[facei] == -1 && nei[facei] != -1)
895 {
896 // Boundary face with incorrect orientation
897 boundaryFaces[facei].flip();
898 std::swap(own[facei], nei[facei]);
899 nReverse++;
900 }
901 }
902 if (nReverse > 0)
903 {
904 Info << "Found " << nReverse << " reversed boundary faces out of "
905 << boundaryFaces.size() << endl;
906 }
907
908
909 label cnt = 0;
910 forAll(own, facei)
911 {
912 if (own[facei] != -1 && nei[facei] != -1)
913 {
914 faceToCell[1].insert(facei, own[facei]);
915 faceToCell[0].insert(facei, nei[facei]);
916 cnt++;
917 }
918 }
919
920 if (cnt > 0)
921 {
922 Info << "Of " << boundaryFaces.size() << " so-called"
923 << " boundary faces " << cnt << " belong to two cells "
924 << "and are therefore internal" << endl;
925 }
926 }
927
928 HashTable<labelList> cellZones;
929 HashTable<labelList> faceZones;
930 List<bool> isAPatch(patchNames.size(),true);
931
932 if (dofVertIndices.size())
933 {
934 // Use the vertex constraints to patch. Is of course bit dodgy since
935 // face goes on patch if all its vertices are on a constraint.
936 // Note: very inefficient since goes through all faces (including
937 // internal ones) twice. Should do a construct without patches
938 // and then repatchify.
939
940 Info<< "Using " << dofVertIndices.size()
941 << " DOF sets to detect boundary faces."<< endl;
942
943 // Renumber vertex numbers on constraints
944 forAll(dofVertIndices, patchi)
945 {
946 inplaceRenumber(unvToFoam, dofVertIndices[patchi]);
947 }
948
949
950 // Build labelHashSet of points per dofGroup/patch
951 List<labelHashSet> dofGroups(dofVertIndices.size());
952
953 forAll(dofVertIndices, patchi)
954 {
955 const labelList& foamVerts = dofVertIndices[patchi];
956 dofGroups[patchi].insert(foamVerts);
957 }
958
959 List<DynamicList<face>> dynPatchFaces(dofVertIndices.size());
960
961 forAll(cellVerts, celli)
962 {
963 const cellShape& shape = cellVerts[celli];
964
965 for (const face& f : shape.faces())
966 {
967 label patchi = findPatch(dofGroups, f);
968
969 if (patchi != -1)
970 {
971 dynPatchFaces[patchi].append(f);
972 }
973 }
974 }
975
976 // Transfer
977 patchFaceVerts.setSize(dynPatchFaces.size());
978
979 forAll(dynPatchFaces, patchi)
980 {
981 patchFaceVerts[patchi].transfer(dynPatchFaces[patchi]);
982 }
983 }
984 else
985 {
986 // Use the boundary faces.
987
988 // Construct the patch faces by sorting the boundaryFaces according to
989 // patch.
990 patchFaceVerts.setSize(patchFaceIndices.size());
991
992 Info<< "Sorting boundary faces according to group (patch)" << endl;
993
994 // make sure that no face is used twice on the boundary
995 // (possible for boundary-only faceZones)
996 labelHashSet alreadyOnBoundary;
997
998 // Construct map from boundaryFaceIndices
999 Map<label> boundaryFaceToIndex(invertToMap(boundaryFaceIndices));
1000
1001 forAll(patchFaceVerts, patchi)
1002 {
1003 Info << patchi << ": " << patchNames[patchi] << " is " << flush;
1004
1005 faceList& patchFaces = patchFaceVerts[patchi];
1006 const labelList& faceIndices = patchFaceIndices[patchi];
1007
1008 patchFaces.setSize(faceIndices.size());
1009
1010 bool duplicateFaces = false;
1011
1012 label cnt = 0;
1013 forAll(patchFaces, i)
1014 {
1015 if (boundaryFaceToIndex.found(faceIndices[i]))
1016 {
1017 label bFacei = boundaryFaceToIndex[faceIndices[i]];
1018
1019 if (own[bFacei] != -1 && nei[bFacei] == -1)
1020 {
1021 patchFaces[cnt] = boundaryFaces[bFacei];
1022 cnt++;
1023 if (alreadyOnBoundary.found(bFacei))
1024 {
1025 duplicateFaces = true;
1026 }
1027 }
1028 }
1029 }
1030
1031 if (cnt != patchFaces.size() || duplicateFaces)
1032 {
1033 isAPatch[patchi] = false;
1034
1035 if (verbose)
1036 {
1037 if (cnt != patchFaces.size())
1038 {
1040 << "For patch " << patchi << " there were "
1041 << patchFaces.size()-cnt
1042 << " faces not used because they seem"
1043 << " to be internal. "
1044 << "This seems to be a face or a cell-zone"
1045 << endl;
1046 }
1047 else
1048 {
1050 << "Patch "
1051 << patchi << " has faces that are already "
1052 << " in use on other boundary-patches,"
1053 << " Assuming faceZoneset." << endl;
1054 }
1055 }
1056
1057 patchFaces.clear(); // Assume that this is no patch at all
1058
1059 if (cellCorrespondence[faceIndices[0]] >= 0)
1060 {
1061 Info << "cellZone" << endl;
1062 labelList theCells(faceIndices.size());
1063 forAll(faceIndices, i)
1064 {
1065 if (cellCorrespondence[faceIndices[0]] < 0)
1066 {
1068 << "The face index " << faceIndices[i]
1069 << " was not found amongst the cells."
1070 << " This kills the theory that "
1071 << patchNames[patchi] << " is a cell zone"
1072 << endl
1073 << abort(FatalError);
1074 }
1075 theCells[i] = cellCorrespondence[faceIndices[i]];
1076 }
1077 cellZones.insert(patchNames[patchi], theCells);
1078 }
1079 else
1080 {
1081 Info << "faceZone" << endl;
1082 labelList theFaces(faceIndices.size());
1083 forAll(faceIndices, i)
1084 {
1085 theFaces[i] = boundaryFaceToIndex[faceIndices[i]];
1086 }
1087 faceZones.insert(patchNames[patchi],theFaces);
1088 }
1089 }
1090 else
1091 {
1092 Info << "patch" << endl;
1093
1094 forAll(patchFaces, i)
1095 {
1096 label bFacei = boundaryFaceToIndex[faceIndices[i]];
1097 alreadyOnBoundary.insert(bFacei);
1098 }
1099 }
1100 }
1101 }
1102
1103 pointField polyPoints;
1104 polyPoints.transfer(points);
1105
1106 // Length scaling factor
1107 polyPoints /= lengthScale;
1108
1109
1110 // For debugging: dump boundary faces as OBJ surface mesh
1111 if (args.found("dump"))
1112 {
1113 Info<< "Writing boundary faces to OBJ file boundaryFaces.obj"
1114 << nl << endl;
1115
1116 // Create globally numbered surface
1117 meshedSurface rawSurface(polyPoints, boundaryFaces);
1118
1119 // Write locally numbered surface
1121 (
1122 rawSurface.localPoints(),
1123 rawSurface.localFaces()
1124 ).write(runTime.path()/"boundaryFaces.obj");
1125 }
1126
1127
1128 Info<< "\nConstructing mesh with non-default patches of size:" << nl;
1129 DynamicList<word> usedPatchNames;
1130 DynamicList<faceList> usedPatchFaceVerts;
1131
1132 forAll(patchNames, patchi)
1133 {
1134 if (isAPatch[patchi])
1135 {
1136 Info<< " " << patchNames[patchi] << '\t'
1137 << patchFaceVerts[patchi].size() << nl;
1138 usedPatchNames.append(patchNames[patchi]);
1139 usedPatchFaceVerts.append(patchFaceVerts[patchi]);
1140 }
1141 }
1142 usedPatchNames.shrink();
1143 usedPatchFaceVerts.shrink();
1144
1145 Info<< endl;
1146
1147 // Construct mesh
1149 (
1150 IOobject
1151 (
1153 runTime.constant(),
1154 runTime
1155 ),
1156 std::move(polyPoints),
1157 cellVerts,
1158 usedPatchFaceVerts, // boundaryFaces,
1159 usedPatchNames, // boundaryPatchNames,
1160 wordList(patchNames.size(), polyPatch::typeName), // boundaryPatchTypes,
1161 "defaultFaces", // defaultFacesName
1162 polyPatch::typeName, // defaultFacesType,
1163 wordList() // boundaryPatchPhysicalTypes
1164 );
1165
1166 // Remove files now, to ensure all mesh files written are consistent.
1167 mesh.removeFiles();
1168
1169 if (faceZones.size() || cellZones.size())
1170 {
1171 Info << "Adding cell and face zones" << endl;
1172
1173 List<pointZone*> pZones(0);
1174 List<faceZone*> fZones(faceZones.size());
1175 List<cellZone*> cZones(cellZones.size());
1176
1177 if (cellZones.size())
1178 {
1179 forAll(cellZones.toc(), cnt)
1180 {
1181 word name = cellZones.toc()[cnt];
1182 Info<< " Cell Zone " << name << " " << tab
1183 << cellZones[name].size() << endl;
1184
1185 cZones[cnt] = new cellZone
1186 (
1187 name,
1188 cellZones[name],
1189 cnt,
1190 mesh.cellZones()
1191 );
1192 }
1193 }
1194 if (faceZones.size())
1195 {
1196 const labelList& own = mesh.faceOwner();
1197 const labelList& nei = mesh.faceNeighbour();
1198 const pointField& centers = mesh.faceCentres();
1199 const pointField& points = mesh.points();
1200
1201 forAll(faceZones.toc(), cnt)
1202 {
1203 word name = faceZones.toc()[cnt];
1204 const labelList& oldIndizes = faceZones[name];
1205 labelList indizes(oldIndizes.size());
1206
1207 Info<< " Face Zone " << name << " " << tab
1208 << oldIndizes.size() << endl;
1209
1210 forAll(indizes, i)
1211 {
1212 const label old = oldIndizes[i];
1213 label noveau = -1;
1214
1215 label c1 = faceToCell[0].lookup(old, -1);
1216 label c2 = faceToCell[1].lookup(old, -1);
1217
1218 if (c1 < c2)
1219 {
1220 std::swap(c1, c2);
1221 }
1222 if (c2 == -1)
1223 {
1224 // Boundary face is part of the faceZone
1225 forAll(own, j)
1226 {
1227 if (own[j] == c1)
1228 {
1229 const face& f = boundaryFaces[old];
1230 if (mag(centers[j]- f.centre(points)) < SMALL)
1231 {
1232 noveau = j;
1233 break;
1234 }
1235 }
1236 }
1237 }
1238 else
1239 {
1240 forAll(nei, j)
1241 {
1242 if
1243 (
1244 (c1 == own[j] && c2 == nei[j])
1245 || (c2 == own[j] && c1 == nei[j])
1246 )
1247 {
1248 noveau = j;
1249 break;
1250 }
1251 }
1252 }
1253 assert(noveau > -1);
1254 indizes[i] = noveau;
1255 }
1256 fZones[cnt] = new faceZone
1257 (
1258 faceZones.toc()[cnt],
1259 indizes,
1260 false, // none are flipped
1261 cnt,
1262 mesh.faceZones()
1263 );
1264 }
1265 }
1266 mesh.addZones(pZones, fZones, cZones);
1267
1268 Info << endl;
1269 }
1270
1271 // More precision (for points data)
1273
1274 mesh.write();
1275
1276 Info<< "End\n" << endl;
1277
1278 return 0;
1279}
1280
1281
1282// ************************************************************************* //
bool found
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void transfer(List< T > &list)
Transfer contents of the argument List into this.
void setSize(const label n)
Alias for resize().
void append(const T &val)
Copy append an element to the end of this list.
void push_back(const T &val)
Copy append an element to the end of this list.
DynamicList< T, SizeMin > & shrink()
Calls shrink_to_fit() and returns a reference to the DynamicList.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition HashSet.H:229
A HashTable similar to std::unordered_map.
Definition HashTable.H:124
List< Key > toc() const
The table of contents (the keys) in unsorted order.
Definition HashTable.C:141
bool found(const Key &key) const
Same as contains().
Definition HashTable.H:1370
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
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 transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition List.C:347
void setSize(label n)
Alias for resize().
Definition List.H:536
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
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
T & last()
Access last element of the list, position [size()-1].
Definition UList.H:971
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
An analytical geometric cellShape.
Definition cellShape.H:71
faceList faces() const
Faces of this cell.
Definition cellShapeI.H:254
A subset of mesh cells.
Definition cellZone.H:61
A topoSetCellSource to select all cells based on usage in given faceSet(s), e.g. select cells that ar...
Definition faceToCell.H:187
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
static int compare(const face &a, const face &b)
Compare faces.
Definition face.C:273
A class for handling file names.
Definition fileName.H:75
A line primitive.
Definition line.H:180
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
static word defaultRegion
Return the default region name.
Definition polyMesh.H:406
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
volScalarField & p
dynamicFvMesh & mesh
engineTime & runTime
IOporosityModelList pZones(mesh)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
auto & name
const pointField & points
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define WarningInFunction
Report a warning using Foam::Warning.
constexpr const char *const group
Group name for atomic constants.
const dimensionedScalar c2
Second radiation constant: default SI units: [m.K].
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
Namespace for OpenFOAM.
List< word > wordList
List of word.
Definition fileName.H:60
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values within a list.
Map< label > invertToMap(const labelUList &values)
Create inverse mapping, which is a lookup table into the given list.
Definition ListOps.C:105
List< label > labelList
A List of labels.
Definition List.H:62
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition label.H:63
messageStream Info
Information stream (stdout output on master, null elsewhere).
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values within a list.
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
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
MeshedSurface< face > meshedSurface
pointField vertices(const blockVertexList &bvl)
void sort(UList< T > &list)
Sort the list.
Definition UList.C:283
errorManip< error > abort(error &err)
Definition errorManip.H:139
vector point
Point is a vector.
Definition point.H:37
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
labelList invert(const label len, const labelUList &map)
Create an inverse one-to-one mapping.
Definition ListOps.C:28
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
Ostream & flush(Ostream &os)
Flush stream.
Definition Ostream.H:509
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
constexpr char tab
The tab '\t' character(0x09).
Definition Ostream.H:49
wordList patchNames(nPatches)
labelList f(nPoints)
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299