Loading...
Searching...
No Matches
MeshedSurface.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) 2016-2022 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
27\*---------------------------------------------------------------------------*/
28
29#include "MeshedSurface.H"
31#include "MeshedSurfaceProxy.H"
32#include "mergePoints.H"
33#include "Time.H"
34#include "ListOps.H"
35#include "polyBoundaryMesh.H"
36#include "polyMesh.H"
37#include "surfMesh.H"
39#include "faceTraits.H"
41
42// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
43
44template<class Face>
46{
47 return wordHashSet(*fileExtensionConstructorTablePtr_);
48}
49
50
51template<class Face>
53{
54 return wordHashSet(*writefileExtensionMemberFunctionTablePtr_);
55}
56
57
58template<class Face>
60(
61 const word& fileType,
62 bool verbose
63)
64{
66 (
67 readTypes() | FriendType::readTypes(),
68 fileType,
69 verbose,
70 "reading"
71 );
72}
73
74
75template<class Face>
77(
78 const word& fileType,
79 bool verbose
80)
81{
83 (
84 writeTypes() | ProxyType::writeTypes(),
85 fileType,
86 verbose,
87 "writing"
88 );
89}
90
91
92template<class Face>
94(
95 const fileName& name,
96 bool verbose
97)
98{
99 const word ext =
100 (
101 name.has_ext("gz")
102 ? name.stem().ext()
103 : name.ext()
104 );
105
106 return canReadType(ext, verbose);
107}
108
109
110template<class Face>
111void Foam::MeshedSurface<Face>::write
112(
113 const fileName& name,
114 const MeshedSurface<Face>& surf,
115 IOstreamOption streamOpt,
116 const dictionary& options
118{
119 write(name, name.ext(), surf, streamOpt, options);
120}
121
122
123template<class Face>
124void Foam::MeshedSurface<Face>::write
125(
126 const fileName& name,
127 const word& fileType,
128 const MeshedSurface<Face>& surf,
129 IOstreamOption streamOpt,
130 const dictionary& options
131)
132{
133 if (fileType.empty())
134 {
135 // Handle empty/missing type
136
137 const word ext(name.ext());
138
139 if (ext.empty())
140 {
142 << "Cannot determine format from filename" << nl
143 << " " << name << nl
144 << exit(FatalError);
145 }
146
147 write(name, ext, surf, streamOpt, options);
148 return;
149 }
150
151
152 DebugInFunction << "Writing to " << name << nl;
153
154 auto* mfuncPtr = writefileExtensionMemberFunctionTable(fileType);
155
156 if (!mfuncPtr)
157 {
158 // Delegate to proxy if possible
159 const wordHashSet delegate(ProxyType::writeTypes());
160
161 if (!delegate.found(fileType))
162 {
164 << "Unknown write format " << fileType << nl << nl
165 << "Valid types:" << nl
166 << flatOutput((delegate | writeTypes()).sortedToc()) << nl
167 << exit(FatalError);
168 }
169
170 MeshedSurfaceProxy<Face>(surf).write
171 (
172 name, fileType, streamOpt, options
173 );
174 }
175 else
176 {
177 mfuncPtr(name, surf, streamOpt, options);
179}
180
181
182// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
183
184template<class Face>
186:
187 MeshReference(List<Face>(), pointField()),
188 faceIds_(),
189 zones_()
190{}
191
192
193template<class Face>
195(
196 const MeshedSurface<Face>& surf
197)
198:
199 MeshReference(surf.surfFaces(), surf.points()),
200 faceIds_(surf.faceIds_),
201 zones_(surf.zones_)
202{}
203
204
205template<class Face>
207(
209)
210:
211 MeshReference(List<Face>(), surf.points()), // Copy points only
212 faceIds_(),
213 zones_()
214{
216 this->storedZones() = surf.sortedZones(faceMap);
217
218 // Faces, in the sorted order
219 const List<Face>& origFaces = surf;
220 {
221 List<Face> newFaces(origFaces.size());
222
223 forAll(newFaces, facei)
224 {
225 newFaces[faceMap[facei]] = origFaces[facei];
227
228 this->storedFaces().transfer(newFaces);
229 }
230
231 // FaceIds, in the sorted order
232 const labelList& origIds = surf.faceIds();
233
234 if (origIds.size() == origFaces.size())
235 {
236 labelList newFaceIds(origIds.size());
237
238 forAll(newFaceIds, facei)
239 {
240 newFaceIds[faceMap[facei]] = origIds[facei];
241 }
243 this->storedFaceIds().transfer(newFaceIds);
244 }
245}
246
247
248template<class Face>
250(
251 MeshedSurface<Face>&& surf
252)
253:
256 transfer(surf);
257}
258
259
260template<class Face>
262(
264)
267{
268 transfer(surf);
269}
271
272template<class Face>
274(
275 const pointField& pointLst,
276 const UList<Face>& faceLst,
277 const UList<surfZone>& zoneLst
278)
279:
280 MeshReference(List<Face>(faceLst), pointLst), // Copy construct
281 faceIds_(),
282 zones_(zoneLst)
283{
284 this->checkZones(false); // Non-verbose fix zones
285}
286
287
288template<class Face>
290(
291 pointField&& pointLst,
292 List<Face>&& faceLst,
293 const UList<surfZone>& zoneLst
294)
295:
296 MeshReference(faceLst, pointLst, true), // Move construct
297 faceIds_(),
298 zones_(zoneLst)
299{
300 this->checkZones(false); // Non-verbose fix zones
301}
302
303
304template<class Face>
306(
307 const pointField& pointLst,
308 const UList<Face>& faceLst,
309 const labelUList& zoneSizes,
310 const UList<word>& zoneNames
311)
312:
313 MeshReference(List<Face>(faceLst), pointLst), // Copy construct
314 faceIds_(),
315 zones_()
316{
317 if (zoneSizes.size())
318 {
319 if (zoneNames.size())
320 {
321 addZones(zoneSizes, zoneNames);
322 }
323 else
324 {
325 addZones(zoneSizes);
326 }
327 }
328}
329
330
331template<class Face>
333(
334 pointField&& pointLst,
335 List<Face>&& faceLst,
336 const labelUList& zoneSizes,
337 const UList<word>& zoneNames
338)
339:
340 MeshReference(faceLst, pointLst, true), // Move construct
341 faceIds_(),
342 zones_()
343{
344 if (zoneSizes.size())
345 {
346 if (zoneNames.size())
347 {
348 addZones(zoneSizes, zoneNames);
349 }
350 else
351 {
352 addZones(zoneSizes);
353 }
354 }
355}
356
357
358template<class Face>
360:
361 MeshedSurface<Face>()
362{
363 // Need same face type as surfMesh
364 MeshedSurface<face> surf
365 (
366 mesh.points(),
367 mesh.faces(),
368 mesh.surfZones()
369 );
370
371 this->transcribe(surf);
372}
373
374
375template<class Face>
377(
378 const polyBoundaryMesh& pbm,
379 const bool useGlobalPoints
380)
381:
382 MeshedSurface<Face>()
383{
384 const polyMesh& mesh = pbm.mesh();
385
386 // create zone list
387 surfZoneList newZones(pbm.size());
388
389 label startFacei = 0;
390 label nZone = 0;
391 for (const polyPatch& p : pbm)
392 {
393 if (p.size())
394 {
395 newZones[nZone] = surfZone
396 (
397 p.name(),
398 p.size(),
399 startFacei,
400 nZone
401 );
402
403 ++nZone;
404 startFacei += p.size();
405 }
406 }
407
408 newZones.setSize(nZone);
409
410 // Get a single patch for all boundaries
411 primitivePatch allBoundary(pbm.faces(), mesh.points());
412
413 // Face type as per polyBoundaryMesh
415
416 if (useGlobalPoints)
417 {
418 // use global points, global face addressing
419 surf = MeshedSurface<face>(mesh.points(), allBoundary, newZones);
420 }
421 else
422 {
423 // use local points, local face addressing
425 (
426 allBoundary.localPoints(),
427 allBoundary.localFaces(),
428 newZones
429 );
431
432 this->transcribe(surf);
433}
434
435
436template<class Face>
438(
439 const fileName& name,
440 const word& fileType
441)
442:
444{
445 read(name, fileType);
446}
447
448
449template<class Face>
451:
453{
454 read(name);
455}
456
457
458template<class Face>
460:
462{
463 read(is);
464}
465
466
467template<class Face>
469(
470 const Time& runTime
472:
474{}
475
476
477template<class Face>
479(
480 const Time& runTime,
481 const word& surfName
482)
483:
484 MeshedSurface<Face>()
485{
487 (
489 (
490 "dummyName",
491 runTime.timeName(),
492 runTime,
496 ),
497 surfName
498 );
499
500 // The geometry components, returned via autoPtr
502 (
503 std::move(*(mesh.releaseGeom()))
504 );
505
506 this->transcribe(surf);
507}
508
509
510template<class Face>
512(
513 const IOobject& io,
514 const dictionary& dict,
515 const bool isGlobal
516)
517:
518 MeshedSurface<Face>()
519{
520 fileName fName
521 (
523 );
524
525 this->read(fName, dict.getOrDefault<word>("fileType", word::null));
526
527 this->scalePoints(dict.getOrDefault<scalar>("scale", 0));
528}
529
530
531// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
532
533template<class Face>
535{
537}
538
539
540// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
541
542template<class Face>
544(
545 const labelUList& faceMapNewToOld
546)
547{
548 if (faceMapNewToOld.empty())
549 {
550 return;
551 }
552
553 surfZoneList& zones = storedZones();
554
555 if (zones.size() == 1)
556 {
557 // Single zone case is trivial
558 zones[0].size() = faceMapNewToOld.size();
559 return;
560 }
561
562 // Recalculate the zone start/size
563 label newFacei = 0;
564 label origEndi = 0;
565
566 for (surfZone& zone : zones)
567 {
568 // Adjust zone start
569 zone.start() = newFacei;
570 origEndi += zone.size();
571
572 for (label facei = newFacei; facei < faceMapNewToOld.size(); ++facei)
573 {
574 if (faceMapNewToOld[facei] < origEndi)
575 {
576 ++newFacei;
577 }
578 else
579 {
580 break;
581 }
582 }
583
584 // Adjust zone size
585 zone.size() = newFacei - zone.start();
587}
588
589
590// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
591
592template<class Face>
594{
595 MeshReference::clearOut(); // Topology changes
596
597 storedPoints().clear();
598 storedFaces().clear();
599 storedFaceIds().clear();
600 storedZones().clear();
601}
602
603
604template<class Face>
606{
607 MeshReference::clearGeom(); // Changes areas, normals etc.
608
609 // Adapt for new point positions
610 MeshReference::movePoints(newPoints);
612 // Copy new points
613 storedPoints() = newPoints;
614}
616
617template<class Face>
618void Foam::MeshedSurface<Face>::scalePoints(const scalar scaleFactor)
619{
620 // Avoid bad or no scaling
621 if (scaleFactor > SMALL && !equal(scaleFactor, 1))
622 {
623 // Remove all geometry dependent data
624 this->clearTopology();
626 // Adapt for new point positions
628
629 this->storedPoints() *= scaleFactor;
630 }
631}
632
634// Remove badly degenerate faces, double faces.
635template<class Face>
636void Foam::MeshedSurface<Face>::cleanup(const bool verbose)
637{
638 // Merge points (already done for STL, TRI)
639 stitchFaces(SMALL, verbose);
641 checkFaces(verbose);
642 this->checkTopology(verbose);
643}
645
646template<class Face>
648{
649 this->clearOut(); // Topology changes
650
651 // Remove unused points while walking and renumbering faces
652 // in visit order - walk order as per localFaces()
653
654 labelList oldToCompact(this->points().size(), -1);
655 DynamicList<label> compactPointMap(oldToCompact.size());
656
657 for (auto& f : this->storedFaces())
658 {
659 for (label& pointi : f)
660 {
661 label compacti = oldToCompact[pointi];
662 if (compacti == -1)
663 {
664 compacti = compactPointMap.size();
665 oldToCompact[pointi] = compacti;
666 compactPointMap.append(pointi);
667 }
668 pointi = compacti;
669 }
670 }
671
672 pointField newPoints
673 (
674 UIndirectList<point>(this->points(), compactPointMap)
675 );
676
677 this->swapPoints(newPoints);
678
679 if (notNull(pointMap))
681 pointMap.transfer(compactPointMap);
682 }
683}
684
685
686template<class Face>
688(
689 const scalar tol,
690 const bool verbose
691)
692{
693 pointField& ps = this->storedPoints();
694
695 // Merge points (inplace)
696 labelList pointMap;
697 label nChanged = Foam::inplaceMergePoints(ps, tol, verbose, pointMap);
698
699 if (!nChanged)
700 {
701 return false;
702 }
703
704 if (verbose)
705 {
706 InfoInFunction<< "Renumbering all faces" << endl;
707 }
708
709 List<Face>& faceLst = this->storedFaces();
710
711 labelList faceMap(faceLst.size(), -1);
712
713 // Reset the point labels to the unique points array
714 label newFacei = 0;
715 forAll(faceLst, facei)
716 {
717 Face& f = faceLst[facei];
718 for (label& vert : f)
719 {
720 vert = pointMap[vert];
721 }
722
723 // For extra safety: collapse face as well
724 if (f.collapse() >= 3)
725 {
726 if (newFacei != facei)
727 {
728 faceLst[newFacei] = f;
729 }
730 faceMap[newFacei] = facei;
731 ++newFacei;
732 }
733 else if (verbose)
734 {
735 Pout<< "MeshedSurface::stitchFaces : "
736 << "Removing collapsed face " << facei << endl
737 << " vertices :" << f << endl;
738 }
739 }
740 pointMap.clear();
741
742 if (newFacei != faceLst.size())
743 {
744 if (verbose)
745 {
746 Pout<< "MeshedSurface::stitchFaces : "
747 << "Removed " << faceLst.size() - newFacei
748 << " faces" << endl;
749 }
750 faceMap.resize(newFacei);
751 faceLst.resize(newFacei);
752
753 // The faceMap is a newToOld mapping and only removes elements
754 if (faceIds_.size())
755 {
756 forAll(faceMap, facei)
758 faceIds_[facei] = faceIds_[faceMap[facei]];
759 }
760
761 faceIds_.resize(newFacei);
763
764 remapFaces(faceMap);
765 }
766 faceMap.clear();
767
768 // Topology can change when points are merged, etc
769 MeshReference::clearOut();
771 return true;
772}
773
774
775// Remove badly degenerate faces and double faces.
776template<class Face>
778(
779 const bool verbose
780)
781{
782 bool changed = false;
783 List<Face>& faceLst = this->storedFaces();
784
785 labelList faceMap(faceLst.size());
786
787 label newFacei = 0;
788 const label maxPointi = this->points().size();
789
790 // Detect badly labelled faces and mark degenerate faces
791 forAll(faceLst, facei)
792 {
793 Face& f = faceLst[facei];
794
795 // Avoid degenerate faces
796 if (f.collapse() >= 3)
797 {
798 for (const label vert : f)
799 {
800 if (vert < 0 || vert >= maxPointi)
801 {
803 << "face " << f
804 << " uses point indices outside point range 0.."
805 << (maxPointi-1)
806 << exit(FatalError);
807 }
808 }
809
810 faceMap[facei] = facei;
811 ++newFacei;
812 }
813 else
814 {
815 // Mark as bad face
816 faceMap[facei] = -1;
817
818 changed = true;
819 if (verbose)
820 {
822 << "face[" << facei << "] = " << f
823 << " does not have three unique vertices" << endl;
824 }
825 }
826 }
827
828 // Detect doubled faces
829 // do not touch the faces
830 const labelListList& fFaces = this->faceFaces();
831 newFacei = 0;
832 forAll(faceLst, facei)
833 {
834 // Skip already collapsed faces
835 if (faceMap[facei] < 0)
836 {
837 continue;
838 }
839
840 const Face& f = faceLst[facei];
841
842 // Duplicate face check
843 bool okay = true;
844 const labelList& neighbours = fFaces[facei];
845
846 // Check if faceNeighbours use same points as this face.
847 // Note: discards normal information - sides of baffle are merged.
848 for (const label neiFacei : neighbours)
849 {
850 if (neiFacei <= facei || faceMap[neiFacei] < 0)
851 {
852 // lower numbered faces already checked
853 // skip neighbours that are themselves collapsed
854 continue;
855 }
856
857 const Face& nei = faceLst[neiFacei];
858
859 if (f == nei)
860 {
861 okay = false;
862
863 if (verbose)
864 {
866 << "faces share the same vertices:" << nl
867 << " face[" << facei << "] : " << f << nl
868 << " face[" << neiFacei << "] : " << nei << endl;
869 // printFace(Warning, " ", f, points());
870 // printFace(Warning, " ", nei, points());
871 }
872
873 break;
874 }
875 }
876
877 if (okay)
878 {
879 faceMap[facei] = facei;
880 ++newFacei;
881 }
882 else
883 {
884 faceMap[facei] = -1;
885 }
886 }
887
888
889 // Until now, faceMap is an identity for good faces and -1 for bad faces
890
891 // Phase 1: pack
892 // Done to keep numbering constant in phase 1
893
894 if (changed || newFacei < faceLst.size())
895 {
896 changed = true;
897
898 if (verbose)
899 {
901 << "Removed " << faceLst.size() - newFacei
902 << " illegal faces." << endl;
903 }
904
905 // Compress the face list
906 newFacei = 0;
907 forAll(faceLst, facei)
908 {
909 if (faceMap[facei] >= 0)
910 {
911 if (newFacei != facei)
912 {
913 faceLst[newFacei] = std::move(faceLst[facei]);
914 }
915 faceMap[newFacei] = facei;
916 ++newFacei;
917 }
918 }
919
920 faceMap.resize(newFacei);
921 faceLst.resize(newFacei);
922
923 // The faceMap is a newToOld mapping and only removes elements
924 if (faceIds_.size())
925 {
926 forAll(faceMap, facei)
927 {
928 faceIds_[facei] = faceIds_[faceMap[facei]];
929 }
930
931 faceIds_.resize(newFacei);
932 }
933
934 remapFaces(faceMap);
935 }
936 faceMap.clear();
937
938 // Topology can change because of renumbering
940 return changed;
941}
942
943
944template<class Face>
946{
948 {
949 return MeshReference::size();
950 }
951
952 return nTriangles
954 const_cast<labelList&>(labelList::null())
955 );
956}
957
958
959template<class Face>
961(
963) const
964{
965 label nTri = 0;
966 const List<Face>& faceLst = surfFaces();
967
968 // Count triangles needed
969 for (const auto& f : faceLst)
970 {
971 nTri += f.nTriangles();
972 }
973
974 // Nothing to do
975 if (nTri <= faceLst.size())
976 {
977 if (notNull(faceMap))
978 {
979 faceMap.clear();
980 }
981 }
982 else if (notNull(faceMap))
983 {
984 // Face map requested
985 faceMap.resize(nTri);
986
987 nTri = 0;
988 forAll(faceLst, facei)
989 {
990 label n = faceLst[facei].nTriangles();
991 while (n-- > 0)
992 {
993 faceMap[nTri++] = facei;
994 }
995 }
996
997 faceMap.resize(nTri);
999
1000 return nTri;
1001}
1002
1003
1004template<class Face>
1006{
1008 {
1009 // Inplace triangulation of triFace/labelledTri surface = no-op
1010 return 0;
1011 }
1012 else
1013 {
1014 return triangulate
1015 (
1017 );
1018 }
1019}
1020
1021
1022template<class Face>
1024(
1025 labelList& faceMapOut
1026)
1027{
1028 labelList dummyFaceMap;
1029
1031 (
1032 notNull(faceMapOut)
1033 ? faceMapOut
1034 : dummyFaceMap
1035 );
1036
1038 {
1039 // Inplace triangulation of triFace/labelledTri surface = no-op
1040 faceMap.clear();
1041 return 0;
1042 }
1043
1044 label nTri = 0;
1045 label maxTri = 0; // the maximum number of triangles for any single face
1046 List<Face>& faceLst = this->storedFaces();
1047
1048 // How many triangles will be needed
1049 for (const auto& f : faceLst)
1050 {
1051 const label n = f.nTriangles();
1052 if (maxTri < n)
1053 {
1054 maxTri = n;
1055 }
1056 nTri += n;
1057 }
1058
1059 // Nothing to do
1060 if (nTri <= faceLst.size())
1061 {
1062 faceMap.clear();
1063 return 0;
1064 }
1065
1066 this->storedFaceIds().clear(); // Invalid or misleading
1067
1068 List<Face> newFaces(nTri);
1069 faceMap.resize(nTri);
1070
1071 if (this->points().empty())
1072 {
1073 // triangulate without points
1074 // simple face triangulation around f[0]
1075 nTri = 0;
1076 forAll(faceLst, facei)
1077 {
1078 const Face& f = faceLst[facei];
1079
1080 for (label fp = 1; fp < f.size() - 1; ++fp)
1081 {
1082 const label fp1 = f.fcIndex(fp);
1083
1084 newFaces[nTri] = Face{f[0], f[fp], f[fp1]};
1085 faceMap[nTri] = facei;
1086 ++nTri;
1087 }
1088 }
1089 }
1090 else
1091 {
1092 // triangulate with points
1093 List<face> tmpTri(maxTri);
1094
1095 nTri = 0;
1096 forAll(faceLst, facei)
1097 {
1098 // 'face' not '<Face>'
1099 const face& f = faceLst[facei];
1100
1101 label nTmp = 0;
1102 f.triangles(this->points(), nTmp, tmpTri);
1103 for (label triI = 0; triI < nTmp; triI++)
1104 {
1105 newFaces[nTri] = Face
1106 (
1107 static_cast<labelUList&>(tmpTri[triI])
1108 );
1109 faceMap[nTri] = facei;
1110 ++nTri;
1111 }
1112 }
1113 }
1114
1115 // The number of *additional* faces
1116 nTri -= faceLst.size();
1117
1118 faceLst.transfer(newFaces);
1119 remapFaces(faceMap);
1120
1121 // Topology can change because of renumbering
1122 MeshReference::clearOut();
1123
1124 return nTri;
1125}
1126
1127
1128template<class Face>
1129Foam::MeshedSurface<Face>
1130Foam::MeshedSurface<Face>::subsetMeshImpl
1131(
1132 const labelList& pointMap,
1133 const labelList& faceMap
1134) const
1135{
1136 const pointField& locPoints = this->localPoints();
1137 const List<Face>& locFaces = this->localFaces();
1138
1139 // Subset of points (compact)
1140 pointField newPoints(UIndirectList<point>(locPoints, pointMap));
1141
1142 // Inverse point mapping - same as ListOps invert() without checks
1143 labelList oldToNew(locPoints.size(), -1);
1144 forAll(pointMap, pointi)
1145 {
1146 oldToNew[pointMap[pointi]] = pointi;
1147 }
1148
1149 // Subset of faces
1150 List<Face> newFaces(UIndirectList<Face>(locFaces, faceMap));
1151
1152 // Renumber face node labels
1153 for (auto& f : newFaces)
1154 {
1155 for (label& vert : f)
1156 {
1157 vert = oldToNew[vert];
1158 }
1159 }
1160 oldToNew.clear();
1161
1162 // Deep copy of zones, leave start/size intact!!
1163 surfZoneList newZones(zones_);
1164
1165 // Recalculate the zone start/size
1166 label newFacei = 0;
1167 label origEndi = 0;
1168
1169 for (surfZone& zone : newZones)
1170 {
1171 // The old zone ending
1172 origEndi += zone.size();
1173
1174 // The new zone start
1175 zone.start() = newFacei;
1176
1177 for (label facei = newFacei; facei < faceMap.size(); ++facei)
1178 {
1179 if (faceMap[facei] < origEndi)
1180 {
1181 ++newFacei;
1182 }
1183 else
1184 {
1185 break;
1186 }
1187 }
1188
1189 // The new zone size
1190 zone.size() = newFacei - zone.start();
1191 }
1192
1193
1194 // Subset of faceIds. Can be empty.
1195 labelList newFaceIds;
1196 if (faceIds_.size())
1197 {
1198 newFaceIds = labelUIndList(faceIds_, faceMap);
1199 }
1200
1201 // Construct the sub-surface
1202 MeshedSurface<Face> newSurf;
1203 newSurf.storedFaces().transfer(newFaces);
1204 newSurf.storedPoints().transfer(newPoints);
1205 newSurf.storedZones().transfer(newZones);
1206 newSurf.storedFaceIds().transfer(newFaceIds);
1208 return newSurf;
1209}
1210
1211
1212template<class Face>
1215(
1216 const UList<bool>& include,
1217 labelList& pointMap,
1219) const
1220{
1221 this->subsetMeshMap(include, pointMap, faceMap);
1222 return this->subsetMeshImpl(pointMap, faceMap);
1223}
1224
1225
1226template<class Face>
1229(
1230 const bitSet& include,
1231 labelList& pointMap,
1233) const
1234{
1235 this->subsetMeshMap(include, pointMap, faceMap);
1236 return this->subsetMeshImpl(pointMap, faceMap);
1237}
1238
1239
1240template<class Face>
1243(
1244 const UList<bool>& include
1245) const
1246{
1248 return this->subsetMesh(include, pointMap, faceMap);
1249}
1250
1251
1252template<class Face>
1255(
1256 const bitSet& include
1257) const
1259 labelList pointMap, faceMap;
1260 return this->subsetMesh(include, pointMap, faceMap);
1261}
1262
1263
1264template<class Face>
1266(
1267 const wordRes& includeNames,
1268 const wordRes& excludeNames
1269) const
1270{
1271 bitSet include(this->size());
1272
1273 for
1274 (
1275 const label zonei
1277 (
1278 zones_,
1279 includeNames,
1280 excludeNames
1281 )
1282 )
1283 {
1284 include.set(zones_[zonei].range());
1286
1287 return this->subsetMesh(include);
1288}
1289
1290
1291template<class Face>
1293(
1294 MeshedSurface<Face>& surf
1295)
1296{
1297 if (this == &surf)
1298 {
1299 return; // Self-swap is a no-op
1300 }
1301
1302 MeshReference::clearOut(); // Topology changes
1303 surf.clearOut(); // Topology changes
1304
1305 this->storedPoints().swap(surf.storedPoints());
1306 this->storedFaces().swap(surf.storedFaces());
1307 this->storedZones().swap(surf.storedZones());
1308 this->storedFaceIds().swap(surf.storedFaceIds());
1309}
1310
1311
1312template<class Face>
1314(
1315 pointField& pointLst,
1316 List<Face>& faceLst
1317)
1318{
1319 MeshReference::clearOut(); // Topology changes
1320
1321 this->storedPoints().transfer(pointLst);
1322 this->storedFaces().transfer(faceLst);
1323 this->storedZones().clear();
1324 this->storedFaceIds().clear(); // Likely to be invalid
1325}
1326
1327
1328template<class Face>
1330(
1332)
1333{
1334 if (this == &surf)
1335 {
1336 return; // Self-assigment is a no-op
1337 }
1338
1339 MeshReference::clearOut(); // Topology changes
1340
1341 this->storedPoints().transfer(surf.storedPoints());
1342 this->storedFaces().transfer(surf.storedFaces());
1343 this->storedZones().transfer(surf.storedZones());
1344 this->storedFaceIds().transfer(surf.storedFaceIds());
1345
1346 surf.clear();
1347}
1348
1349
1350template<class Face>
1352(
1354)
1355{
1356 // Clear everything
1357 this->clear();
1358
1360 surfZoneList zoneLst = surf.sortedZones(faceMap);
1361
1362 List<Face>& faceLst = surf.storedFaces();
1363
1364 if (zoneLst.size() > 1)
1365 {
1366 // Unknown if we really need to sort the faces
1367 List<Face> sortedFaces(faceMap.size());
1368
1369 forAll(faceMap, facei)
1370 {
1371 sortedFaces[faceMap[facei]].transfer(faceLst[facei]);
1372 }
1373
1374 faceLst.swap(sortedFaces); // Replace with sorted faces
1375 }
1376
1377 MeshedSurface<Face> newSurf
1378 (
1379 std::move(surf.storedPoints()),
1380 std::move(faceLst),
1381 zoneLst
1382 );
1383
1384 surf.clear();
1386 this->swap(newSurf);
1387}
1388
1389
1390template<class Face>
1393{
1394 return autoPtr<MeshedSurface<Face>>::New(std::move(*this));
1395}
1396
1397
1398template<class Face>
1400{
1401 MeshReference::clearOut(); // Topology changes
1402
1403 this->storedFaceIds().clear(); // Likely to be invalid
1404
1405 this->storedFaces().swap(faces);
1406
1407 this->checkZones(false); // Non-verbose fix zones
1408}
1409
1410
1411template<class Face>
1413{
1414 // Adapt for new point positions
1416
1417 this->storedPoints().swap(points);
1418}
1419
1420
1421template<class Face>
1422bool Foam::MeshedSurface<Face>::read(const fileName& name)
1423{
1424 this->clear();
1425 transfer(*New(name));
1426 return true;
1427}
1428
1429
1430template<class Face>
1431bool Foam::MeshedSurface<Face>::read
1432(
1433 const fileName& name,
1434 const word& fileType
1435)
1436{
1437 this->clear();
1438 transfer(*New(name, fileType));
1439 return true;
1440}
1441
1442
1443template<class Face>
1444void Foam::MeshedSurface<Face>::write
1445(
1446 const Time& t,
1447 const word& surfName
1448) const
1449{
1450 MeshedSurfaceProxy<Face>(*this).write(t, surfName);
1451}
1452
1453
1454// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1455
1456template<class Face>
1458{
1459 if (this == &surf)
1460 {
1461 return; // Self-assignment is a no-op
1462 }
1463
1464 // Clear everything
1465 this->clear();
1466
1467 this->storedPoints() = surf.points();
1468 this->storedFaces() = surf.surfFaces();
1469 this->storedFaceIds() = surf.faceIds();
1470 this->storedZones() = surf.surfZones();
1471}
1472
1473
1474template<class Face>
1476{
1477 transfer(surf);
1478}
1479
1480
1481template<class Face>
1483{
1484 return MeshedSurfaceProxy<Face>
1485 (
1486 this->points(),
1487 this->surfFaces(),
1488 this->surfZones(),
1489 labelUList::null(), // faceMap = none
1490 this->faceIds()
1491 );
1492}
1493
1494
1495// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1496
1497#include "MeshedSurfaceZones.C"
1498#include "MeshedSurfaceIO.C"
1499#include "MeshedSurfaceNew.C"
1500
1501// ************************************************************************* //
scalar range
Various functions to operate on Lists.
label n
Macros for easy insertion into run-time selection tables.
const polyBoundaryMesh & pbm
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
bool found(const Key &key) const
Same as contains().
Definition HashTable.H:1370
@ NO_REGISTER
Do not request registration (bool: false).
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
A simple container for options an IOstream can normally have.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
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 resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
static const List< T > & null() noexcept
Return a null List (reference to a nullObject). Behaves like an empty List.
Definition List.H:138
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
static wordHashSet writeTypes()
The file format types that can be written via MeshedSurfaceProxy.
static void write(const fileName &name, const MeshedSurfaceProxy &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &options=dictionary::null)
Write to file, select based on its extension.
A surface geometry mesh with zone information, not to be confused with the similarly named surfaceMes...
MeshedSurface subsetMesh(const UList< bool > &include, labelList &pointMap, labelList &faceMap) const
Return a new surface subsetted on the selected faces.
virtual void movePoints(const pointField &newPoints)
Move points.
surfZoneList & storedZones()
Non-const access to the zones.
static bool canWriteType(const word &fileType, bool verbose=false)
Can we write this file format? Also checks proxy types.
labelList & storedFaceIds()
Non-const access to face ids.
const surfZoneList & surfZones() const
Const access to the surface zones.
pointField & storedPoints()
Non-const access to global points.
static wordHashSet writeTypes()
Known writable file-types, without friends or proxies.
virtual void remapFaces(const labelUList &faceMapNewToOld)
Set new zones from faceMap.
void transfer(pointField &pointLst, List< Face > &faceLst)
Transfer the components.
static bool canReadType(const word &fileType, bool verbose=false)
Can we read this file format? Also checks friend types.
virtual void cleanup(const bool verbose)
Remove invalid faces.
virtual ~MeshedSurface()
Destructor.
virtual label triangulate()
Triangulate in-place, returning the number of triangles added.
void swapPoints(pointField &points)
virtual void compactPoints(labelList &pointMap=const_cast< labelList & >(labelList::null()))
Remove unused points and renumber faces in local visit order.
static bool canRead(const fileName &name, bool verbose=false)
Can we read this file format?
void checkZones(const bool verbose=true)
Sanity check/resizing on zones.
const labelList & faceIds() const
Return const access to faces ids.
const List< face > & surfFaces() const
MeshedSurface(const MeshedSurface< Foam::face > &surf)
void subsetMeshMap(const BoolListType &include, labelList &pointMap, labelList &faceMap) const
Create mappings for a sub-surface.
autoPtr< MeshedSurface< Face > > releaseGeom()
Release (clear) geometry and return for reuse.
virtual label nTriangles() const
Count number of triangles.
List< Face > & storedFaces()
Non-const access to the faces.
void transcribe(MeshedSurface< face > &surf)
Transfer points/zones from 'face' to other other shapes.
void swap(MeshedSurface< Face > &surf)
Swap contents.
virtual void clear()
Clear all storage.
friend class surfMesh
virtual bool stitchFaces(const scalar tol=SMALL, const bool verbose=false)
virtual void scalePoints(const scalar scaleFactor)
Scale points. A non-positive factor is ignored.
friend class UnsortedMeshedSurface
friend class MeshedSurface
virtual bool checkFaces(const bool verbose=false)
void operator=(const MeshedSurface< Face > &surf)
Copy assignment.
void swapFaces(List< Face > &faces)
Swap the stored faces. Use with caution.
static wordHashSet readTypes()
Known readable file-types, without friends or proxies.
const Field< point_type > & localPoints() const
Return pointField of points in patch.
const Field< point_type > & points() const noexcept
virtual void movePoints(const Field< point_type > &)
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
A List with indirect addressing. Like IndirectList but does not store addressing.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
void swap(UList< T > &list) noexcept
Swap content with another UList of the same type in constant time.
Definition UListI.H:524
static const UList< label > & null() noexcept
Definition UList.H:225
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
label fcIndex(const label i) const noexcept
The forward circular index. The next index in the list which returns to the first at the end of the l...
Definition UListI.H:99
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
surfZoneList sortedZones(labelList &faceMap) const
Sort faces according to zoneIds.
void transfer(UnsortedMeshedSurface< Face > &surf)
Transfer the contents of the argument and annul the argument.
virtual void clear()
Clear all storage.
static wordHashSet readTypes()
Known readable file-types, without friends or proxies.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition bitSet.H:61
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition bitSetI.H:502
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
static bool isTri()
Face-type only handles triangles. Not true in general.
Definition faceTraits.H:51
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
static labelList getSelectedPatches(const surfZoneList &patches, const wordRes &allow, const wordRes &deny=wordRes())
Return ids for zone/patch that match by name.
static fileName checkFile(const IOobject &io, const bool isGlobal=true)
Return fileName to load IOobject from.
static bool checkSupport(const wordHashSet &available, const word &fileType, const bool verbose=false, const char *functionName=nullptr)
Verbose checking of fileType in the list of available types.
A class for handling file names.
Definition fileName.H:75
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
A surface mesh consisting of general polygon faces that has IO capabilities and a registry for storin...
Definition surfMesh.H:67
A surface zone on a MeshedSurface.
Definition surfZone.H:55
A List of wordRe with additional matching capabilities.
Definition wordRes.H:56
A class for handling words, derived from Foam::string.
Definition word.H:66
static const word null
An empty word.
Definition word.H:84
Base class for mesh zones.
Definition zone.H:63
volScalarField & p
dynamicFvMesh & mesh
engineTime & runTime
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const auto & io
auto & name
const pointField & points
Geometric merging of points. See below.
surface1 clear()
#define WarningInFunction
Report a warning using Foam::Warning.
#define DebugInFunction
Report an information message using Foam::Info.
#define InfoInFunction
Report an information message using Foam::Info.
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to 'true' entries.
Definition BitOps.C:200
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition HashSet.H:80
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition int32.H:127
List< label > labelList
A List of labels.
Definition List.H:62
label checkTopology(const polyMesh &mesh, const bool allTopology, const bool allGeometry, autoPtr< surfaceWriter > &surfWriter, autoPtr< coordSetWriter > &setWriter, const bool writeBadEdges=false)
UIndirectList< label > labelUIndList
UIndirectList of labels.
List< surfZone > surfZoneList
List of surfZone.
bool equal(const T &a, const T &b)
Compare two values for equality.
Definition label.H:180
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
label checkZones(const polyMesh &mesh, const ZoneMesh< Zone, polyMesh > &zones, topoSet &set)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
label inplaceMergePoints(PointList &points, const scalar mergeTol, const bool verbose, labelList &pointToUnique)
Inplace merge points, preserving the original point order. All points closer/equal mergeTol are to be...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
bool notNull(const T *ptr) noexcept
True if ptr is not a pointer (of type T) to the nullObject.
Definition nullObject.H:267
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
runTime write()
labelList f(nPoints)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299