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