Loading...
Searching...
No Matches
polyMeshAdder.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) 2019-2023 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 "polyMeshAdder.H"
30#include "mapAddedPolyMesh.H"
31#include "IOobject.H"
32#include "faceCoupleInfo.H"
33#include "processorPolyPatch.H"
34#include "SortableList.H"
35#include "Time.H"
36#include "globalMeshData.H"
37#include "mergePoints.H"
38#include "polyModifyFace.H"
39#include "polyRemovePoint.H"
40#include "polyTopoChange.H"
41#include "globalIndex.H"
42
43// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44
45// Get index of patch in new set of patchnames/types
46Foam::label Foam::polyMeshAdder::patchIndex
47(
48 const polyPatch& p,
49 DynamicList<word>& allPatchNames,
50 DynamicList<word>& allPatchTypes
51)
52{
53 // Find the patch name on the list. If the patch is already there
54 // and patch types match, return index
55 const word& pType = p.type();
56 const word& pName = p.name();
57
58 label patchi = allPatchNames.find(pName);
59
60 if (patchi < 0)
61 {
62 // Not found - add to the lists
63 patchi = allPatchNames.size();
64
65 allPatchNames.push_back(pName);
66 allPatchTypes.push_back(pType);
67 }
68 else if (allPatchTypes[patchi] != pType)
69 {
70 // Found the name, but type is different
71 patchi = allPatchNames.size();
72
73 // Duplicate name is not allowed. Create a composite name from the
74 // patch name and case name
75 const word& caseName = p.boundaryMesh().mesh().time().caseName();
76
77 allPatchNames.push_back(pName + "_" + caseName);
78 allPatchTypes.push_back(pType);
79
80 Pout<< "label patchIndex(const polyPatch& p) : "
81 << "Patch " << p.index() << " named "
82 << pName << " in mesh " << caseName
83 << " already exists, but patch types"
84 << " do not match.\nCreating a composite name as "
85 << allPatchNames.back() << endl;
86 }
87
88 return patchi;
89}
90
91
92// Get index of zone in new set of zone names
93Foam::label Foam::polyMeshAdder::zoneIndex
94(
95 const word& curName,
97)
98{
99 label zonei = names.find(curName);
100
101 if (zonei < 0)
102 {
103 // Not found - add to the list
104 zonei = names.size();
105
106 names.push_back(curName);
107 }
108
109 return zonei;
110}
111
112
113void Foam::polyMeshAdder::mergePatchNames
114(
115 const polyBoundaryMesh& patches0,
116 const polyBoundaryMesh& patches1,
117
118 DynamicList<word>& allPatchNames,
119 DynamicList<word>& allPatchTypes,
120
121 labelList& from1ToAllPatches,
122 labelList& fromAllTo1Patches
123)
124{
125 // Insert the mesh0 patches and zones
126 allPatchNames.push_back(patches0.names());
127 allPatchTypes.push_back(patches0.types());
128
129
130 // Patches
131 // ~~~~~~~
132 // Patches from 0 are taken over as is; those from 1 get either merged
133 // (if they share name and type) or appended.
134 // Empty patches are filtered out much much later on.
135
136 // Add mesh1 patches and build map both ways.
137 from1ToAllPatches.setSize(patches1.size());
138
139 forAll(patches1, patchi)
140 {
141 from1ToAllPatches[patchi] = patchIndex
142 (
143 patches1[patchi],
144 allPatchNames,
145 allPatchTypes
146 );
147 }
148 allPatchTypes.shrink();
149 allPatchNames.shrink();
150
151 // Invert 1 to all patch map
152 fromAllTo1Patches.setSize(allPatchNames.size());
153 fromAllTo1Patches = -1;
154
155 forAll(from1ToAllPatches, i)
156 {
157 fromAllTo1Patches[from1ToAllPatches[i]] = i;
158 }
159}
160
161
162Foam::List<Foam::polyPatch*> Foam::polyMeshAdder::combinePatches
163(
164 const polyMesh& mesh0,
165 const polyMesh& mesh1,
166 const polyBoundaryMesh& allBoundaryMesh,
167 const label nAllPatches,
168 const labelList& fromAllTo1Patches,
169
170 const label nInternalFaces,
171 const labelList& nFaces,
172
173 labelList& from0ToAllPatches,
174 labelList& from1ToAllPatches
175)
176{
177 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
178 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
179
180
181 // Compacted new patch list.
182 DynamicList<polyPatch*> allPatches(nAllPatches);
183
184
185 // Map from 0 to all patches (since gets compacted)
186 from0ToAllPatches.setSize(patches0.size());
187 from0ToAllPatches = -1;
188
189 label startFacei = nInternalFaces;
190
191 // Copy patches0 with new sizes. First patches always come from
192 // mesh0 and will always be present.
193 forAll(patches0, patchi)
194 {
195 // Originates from mesh0. Clone with new size & filter out empty
196 // patch.
197 label filteredPatchi;
198
199 if (nFaces[patchi] == 0 && isA<processorPolyPatch>(patches0[patchi]))
200 {
201 //Pout<< "Removing zero sized mesh0 patch "
202 // << patches0[patchi].name() << endl;
203 filteredPatchi = -1;
204 }
205 else
206 {
207 filteredPatchi = allPatches.size();
208
209 allPatches.append
210 (
211 patches0[patchi].clone
212 (
213 allBoundaryMesh,
214 filteredPatchi,
215 nFaces[patchi],
216 startFacei
217 ).ptr()
218 );
219 startFacei += nFaces[patchi];
220 }
221
222 // Record new index in allPatches
223 from0ToAllPatches[patchi] = filteredPatchi;
224
225 // Check if patch was also in mesh1 and update its addressing if so.
226 if (fromAllTo1Patches[patchi] != -1)
227 {
228 from1ToAllPatches[fromAllTo1Patches[patchi]] = filteredPatchi;
229 }
230 }
231
232 // Copy unique patches of mesh1.
233 forAll(from1ToAllPatches, patchi)
234 {
235 label allPatchi = from1ToAllPatches[patchi];
236
237 if (allPatchi >= patches0.size())
238 {
239 // Patch has not been merged with any mesh0 patch.
240
241 label filteredPatchi;
242
243 if
244 (
245 nFaces[allPatchi] == 0
246 && isA<processorPolyPatch>(patches1[patchi])
247 )
248 {
249 //Pout<< "Removing zero sized mesh1 patch "
250 // << patches1[patchi].name() << endl;
251 filteredPatchi = -1;
252 }
253 else
254 {
255 filteredPatchi = allPatches.size();
256
257 allPatches.append
258 (
259 patches1[patchi].clone
260 (
261 allBoundaryMesh,
262 filteredPatchi,
263 nFaces[allPatchi],
264 startFacei
265 ).ptr()
266 );
267 startFacei += nFaces[allPatchi];
268 }
269
270 from1ToAllPatches[patchi] = filteredPatchi;
271 }
272 }
273
274 allPatches.shrink();
275
276 return allPatches;
277}
278
279
280Foam::labelList Foam::polyMeshAdder::getFaceOrder
281(
282 const cellList& cells,
283 const label nInternalFaces,
284 const labelList& owner,
285 const labelList& neighbour
286)
287{
288 labelList oldToNew(owner.size(), -1);
289
290 // Leave boundary faces in order
291 for (label facei = nInternalFaces; facei < owner.size(); ++facei)
292 {
293 oldToNew[facei] = facei;
294 }
295
296 // First unassigned face
297 label newFacei = 0;
298
299 forAll(cells, celli)
300 {
301 const labelList& cFaces = cells[celli];
302
303 SortableList<label> nbr(cFaces.size());
304
305 forAll(cFaces, i)
306 {
307 const label facei = cFaces[i];
308
309 label nbrCelli = neighbour[facei];
310
311 if (nbrCelli != -1)
312 {
313 // Internal face. Get cell on other side.
314 if (nbrCelli == celli)
315 {
316 nbrCelli = owner[facei];
317 }
318
319 if (celli < nbrCelli)
320 {
321 // Celli is master
322 nbr[i] = nbrCelli;
323 }
324 else
325 {
326 // nbrCell is master. Let it handle this face.
327 nbr[i] = -1;
328 }
329 }
330 else
331 {
332 // External face. Do later.
333 nbr[i] = -1;
334 }
335 }
336
337 nbr.sort();
338
339 forAll(nbr, i)
340 {
341 if (nbr[i] != -1)
342 {
343 oldToNew[cFaces[nbr.indices()[i]]] = newFacei++;
344 }
345 }
346 }
347
348
349 // Check done all faces.
350 forAll(oldToNew, facei)
351 {
352 if (oldToNew[facei] == -1)
353 {
355 << "Did not determine new position"
356 << " for face " << facei
357 << abort(FatalError);
358 }
359 }
360
361 return oldToNew;
362}
363
364
365// Extends face f with split points. cutEdgeToPoints gives for every
366// edge the points introduced inbetween the endpoints.
367void Foam::polyMeshAdder::insertVertices
368(
369 const EdgeMap<labelList>& cutEdgeToPoints,
370 const Map<label>& meshToMaster,
371 const labelList& masterToCutPoints,
372 const face& masterF,
373
374 DynamicList<label>& workFace,
375 face& allF
376)
377{
378 workFace.clear();
379
380 // Check any edge for being cut (check on the cut so takes account
381 // for any point merging on the cut)
382
383 forAll(masterF, fp)
384 {
385 label v0 = masterF[fp];
386 label v1 = masterF.nextLabel(fp);
387
388 // Copy existing face point
389 workFace.append(allF[fp]);
390
391 // See if any edge between v0,v1
392
393 const auto v0Fnd = meshToMaster.cfind(v0);
394 if (v0Fnd.good())
395 {
396 const auto v1Fnd = meshToMaster.cfind(v1);
397 if (v1Fnd.good())
398 {
399 // Get edge in cutPoint numbering
400 edge cutEdge
401 (
402 masterToCutPoints[v0Fnd()],
403 masterToCutPoints[v1Fnd()]
404 );
405
406 const auto iter = cutEdgeToPoints.cfind(cutEdge);
407
408 if (iter.good())
409 {
410 const edge& e = iter.key();
411 const labelList& addedPoints = iter.val();
412
413 // cutPoints first in allPoints so no need for renumbering
414 if (e[0] == cutEdge[0])
415 {
416 forAll(addedPoints, i)
417 {
418 workFace.append(addedPoints[i]);
419 }
420 }
421 else
422 {
423 forAllReverse(addedPoints, i)
424 {
425 workFace.append(addedPoints[i]);
426 }
427 }
428 }
429 }
430 }
431 }
432
433 if (workFace.size() != allF.size())
434 {
435 allF.transfer(workFace);
436 }
437}
438
439
440// Adds primitives (cells, faces, points)
441// Cells:
442// - all of mesh0
443// - all of mesh1
444// Faces:
445// - all uncoupled of mesh0
446// - all coupled faces
447// - all uncoupled of mesh1
448// Points:
449// - all coupled
450// - all uncoupled of mesh0
451// - all uncoupled of mesh1
452void Foam::polyMeshAdder::mergePrimitives
453(
454 const polyMesh& mesh0,
455 const polyMesh& mesh1,
456 const faceCoupleInfo& coupleInfo,
457
458 const label nAllPatches, // number of patches in the new mesh
459 const labelList& fromAllTo1Patches,
460 const labelList& from1ToAllPatches,
461
462 pointField& allPoints,
463 labelList& from0ToAllPoints,
464 labelList& from1ToAllPoints,
465
466 faceList& allFaces,
467 labelList& allOwner,
468 labelList& allNeighbour,
469 label& nInternalFaces,
470 labelList& nFacesPerPatch,
471 label& nCells,
472
473 labelList& from0ToAllFaces,
474 labelList& from1ToAllFaces,
475 labelList& from1ToAllCells
476)
477{
478 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
479 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
480
481 const primitiveFacePatch& cutFaces = coupleInfo.cutFaces();
482 const indirectPrimitivePatch& masterPatch = coupleInfo.masterPatch();
483 const indirectPrimitivePatch& slavePatch = coupleInfo.slavePatch();
484
485
486 // Points
487 // ~~~~~~
488
489 // Storage for new points
490 allPoints.setSize(mesh0.nPoints() + mesh1.nPoints());
491 label allPointi = 0;
492
493 from0ToAllPoints.setSize(mesh0.nPoints());
494 from0ToAllPoints = -1;
495 from1ToAllPoints.setSize(mesh1.nPoints());
496 from1ToAllPoints = -1;
497
498 // Copy coupled points (on cut)
499 {
500 const pointField& cutPoints = coupleInfo.cutPoints();
501
502 //const labelListList& cutToMasterPoints =
503 // coupleInfo.cutToMasterPoints();
504 labelListList cutToMasterPoints
505 (
507 (
508 cutPoints.size(),
509 coupleInfo.masterToCutPoints()
510 )
511 );
512
513 //const labelListList& cutToSlavePoints =
514 // coupleInfo.cutToSlavePoints();
515 labelListList cutToSlavePoints
516 (
518 (
519 cutPoints.size(),
520 coupleInfo.slaveToCutPoints()
521 )
522 );
523
524 forAll(cutPoints, i)
525 {
526 allPoints[allPointi] = cutPoints[i];
527
528 // Mark all master and slave points referring to this point.
529
530 const labelList& masterPoints = cutToMasterPoints[i];
531
532 forAll(masterPoints, j)
533 {
534 label mesh0Pointi = masterPatch.meshPoints()[masterPoints[j]];
535 from0ToAllPoints[mesh0Pointi] = allPointi;
536 }
537
538 const labelList& slavePoints = cutToSlavePoints[i];
539
540 forAll(slavePoints, j)
541 {
542 label mesh1Pointi = slavePatch.meshPoints()[slavePoints[j]];
543 from1ToAllPoints[mesh1Pointi] = allPointi;
544 }
545 allPointi++;
546 }
547 }
548
549 // Add uncoupled mesh0 points
550 forAll(mesh0.points(), pointi)
551 {
552 if (from0ToAllPoints[pointi] == -1)
553 {
554 allPoints[allPointi] = mesh0.points()[pointi];
555 from0ToAllPoints[pointi] = allPointi;
556 allPointi++;
557 }
558 }
559
560 // Add uncoupled mesh1 points
561 forAll(mesh1.points(), pointi)
562 {
563 if (from1ToAllPoints[pointi] == -1)
564 {
565 allPoints[allPointi] = mesh1.points()[pointi];
566 from1ToAllPoints[pointi] = allPointi;
567 allPointi++;
568 }
569 }
570
571 allPoints.setSize(allPointi);
572
573
574 // Faces
575 // ~~~~~
576
577 // Sizes per patch
578 nFacesPerPatch.setSize(nAllPatches);
579 nFacesPerPatch = 0;
580
581 // Storage for faces and owner/neighbour
582 allFaces.setSize(mesh0.nFaces() + mesh1.nFaces());
583 allOwner.setSize(allFaces.size());
584 allOwner = -1;
585 allNeighbour.setSize(allFaces.size());
586 allNeighbour = -1;
587 label allFacei = 0;
588
589 from0ToAllFaces.setSize(mesh0.nFaces());
590 from0ToAllFaces = -1;
591 from1ToAllFaces.setSize(mesh1.nFaces());
592 from1ToAllFaces = -1;
593
594 // Copy mesh0 internal faces (always uncoupled)
595 for (label facei = 0; facei < mesh0.nInternalFaces(); facei++)
596 {
597 allFaces[allFacei] = renumber(from0ToAllPoints, mesh0.faces()[facei]);
598 allOwner[allFacei] = mesh0.faceOwner()[facei];
599 allNeighbour[allFacei] = mesh0.faceNeighbour()[facei];
600 from0ToAllFaces[facei] = allFacei++;
601 }
602
603 // Copy coupled faces. Every coupled face has an equivalent master and
604 // slave. Also uncount as boundary faces all the newly coupled faces.
605 const labelList& cutToMasterFaces = coupleInfo.cutToMasterFaces();
606 const labelList& cutToSlaveFaces = coupleInfo.cutToSlaveFaces();
607
608 forAll(cutFaces, i)
609 {
610 label masterFacei = cutToMasterFaces[i];
611
612 label mesh0Facei = masterPatch.addressing()[masterFacei];
613
614 if (from0ToAllFaces[mesh0Facei] == -1)
615 {
616 // First occurrence of face
617 from0ToAllFaces[mesh0Facei] = allFacei;
618
619 // External face becomes internal so uncount
620 label patch0 = patches0.whichPatch(mesh0Facei);
621 nFacesPerPatch[patch0]--;
622 }
623
624 label slaveFacei = cutToSlaveFaces[i];
625
626 label mesh1Facei = slavePatch.addressing()[slaveFacei];
627
628 if (from1ToAllFaces[mesh1Facei] == -1)
629 {
630 from1ToAllFaces[mesh1Facei] = allFacei;
631
632 label patch1 = patches1.whichPatch(mesh1Facei);
633 nFacesPerPatch[from1ToAllPatches[patch1]]--;
634 }
635
636 // Copy cut face (since cutPoints are copied first no renumbering
637 // necessary)
638 allFaces[allFacei] = cutFaces[i];
639 allOwner[allFacei] = mesh0.faceOwner()[mesh0Facei];
640 allNeighbour[allFacei] = mesh1.faceOwner()[mesh1Facei] + mesh0.nCells();
641
642 allFacei++;
643 }
644
645 // Copy mesh1 internal faces (always uncoupled)
646 for (label facei = 0; facei < mesh1.nInternalFaces(); facei++)
647 {
648 allFaces[allFacei] = renumber(from1ToAllPoints, mesh1.faces()[facei]);
649 allOwner[allFacei] = mesh1.faceOwner()[facei] + mesh0.nCells();
650 allNeighbour[allFacei] = mesh1.faceNeighbour()[facei] + mesh0.nCells();
651 from1ToAllFaces[facei] = allFacei++;
652 }
653
654 nInternalFaces = allFacei;
655
656 // Copy (unmarked/uncoupled) external faces in new order.
657 for (label allPatchi = 0; allPatchi < nAllPatches; allPatchi++)
658 {
659 if (allPatchi < patches0.size())
660 {
661 // Patch is present in mesh0
662 const polyPatch& pp = patches0[allPatchi];
663
664 nFacesPerPatch[allPatchi] += pp.size();
665
666 label facei = pp.start();
667
668 forAll(pp, i)
669 {
670 if (from0ToAllFaces[facei] == -1)
671 {
672 // Is uncoupled face since has not yet been dealt with
673 allFaces[allFacei] = renumber
674 (
675 from0ToAllPoints,
676 mesh0.faces()[facei]
677 );
678 allOwner[allFacei] = mesh0.faceOwner()[facei];
679 allNeighbour[allFacei] = -1;
680
681 from0ToAllFaces[facei] = allFacei++;
682 }
683 facei++;
684 }
685 }
686 if (fromAllTo1Patches[allPatchi] != -1)
687 {
688 // Patch is present in mesh1
689 const polyPatch& pp = patches1[fromAllTo1Patches[allPatchi]];
690
691 nFacesPerPatch[allPatchi] += pp.size();
692
693 label facei = pp.start();
694
695 forAll(pp, i)
696 {
697 if (from1ToAllFaces[facei] == -1)
698 {
699 // Is uncoupled face
700 allFaces[allFacei] = renumber
701 (
702 from1ToAllPoints,
703 mesh1.faces()[facei]
704 );
705 allOwner[allFacei] =
706 mesh1.faceOwner()[facei]
707 + mesh0.nCells();
708 allNeighbour[allFacei] = -1;
709
710 from1ToAllFaces[facei] = allFacei++;
711 }
712 facei++;
713 }
714 }
715 }
716 allFaces.setSize(allFacei);
717 allOwner.setSize(allFacei);
718 allNeighbour.setSize(allFacei);
719
720
721 // So now we have all ok for one-to-one mapping.
722 // For split slace faces:
723 // - mesh consistent with slave side
724 // - mesh not consistent with owner side. It is not zipped up, the
725 // original faces need edges split.
726
727 // Use brute force to prevent having to calculate addressing:
728 // - get map from master edge to split edges.
729 // - check all faces to find any edge that is split.
730 {
731 // From two cut-points to labels of cut-points inbetween.
732 // (in order: from e[0] to e[1]
733 const EdgeMap<labelList>& cutEdgeToPoints
734 = coupleInfo.cutEdgeToPoints();
735
736 // Get map of master face (in mesh labels) that are in cut. These faces
737 // do not need to be renumbered.
738 labelHashSet masterCutFaces(cutToMasterFaces.size());
739 forAll(cutToMasterFaces, i)
740 {
741 label meshFacei = masterPatch.addressing()[cutToMasterFaces[i]];
742
743 masterCutFaces.insert(meshFacei);
744 }
745
746 DynamicList<label> workFace(100);
747
748 forAll(from0ToAllFaces, face0)
749 {
750 if (!masterCutFaces.found(face0))
751 {
752 label allFacei = from0ToAllFaces[face0];
753
754 insertVertices
755 (
756 cutEdgeToPoints,
757 masterPatch.meshPointMap(),
758 coupleInfo.masterToCutPoints(),
759 mesh0.faces()[face0],
760
761 workFace,
762 allFaces[allFacei]
763 );
764 }
765 }
766
767 // Same for slave face
768
769 labelHashSet slaveCutFaces(cutToSlaveFaces.size());
770 forAll(cutToSlaveFaces, i)
771 {
772 label meshFacei = slavePatch.addressing()[cutToSlaveFaces[i]];
773
774 slaveCutFaces.insert(meshFacei);
775 }
776
777 forAll(from1ToAllFaces, face1)
778 {
779 if (!slaveCutFaces.found(face1))
780 {
781 label allFacei = from1ToAllFaces[face1];
782
783 insertVertices
784 (
785 cutEdgeToPoints,
786 slavePatch.meshPointMap(),
787 coupleInfo.slaveToCutPoints(),
788 mesh1.faces()[face1],
789
790 workFace,
791 allFaces[allFacei]
792 );
793 }
794 }
795 }
796
797 // Now we have a full facelist and owner/neighbour addressing.
798
799
800 // Cells
801 // ~~~~~
802
803 from1ToAllCells.setSize(mesh1.nCells());
804 from1ToAllCells = -1;
805
806 forAll(mesh1.cells(), i)
807 {
808 from1ToAllCells[i] = i + mesh0.nCells();
809 }
810
811 // Make cells (= cell-face addressing)
812 nCells = mesh0.nCells() + mesh1.nCells();
813 cellList allCells(nCells);
814 primitiveMesh::calcCells(allCells, allOwner, allNeighbour, nCells);
815
816 // Reorder faces for upper-triangular order.
817 labelList oldToNew
818 (
819 getFaceOrder
820 (
821 allCells,
822 nInternalFaces,
823 allOwner,
824 allNeighbour
825 )
826 );
827
828 inplaceReorder(oldToNew, allFaces);
829 inplaceReorder(oldToNew, allOwner);
830 inplaceReorder(oldToNew, allNeighbour);
831 inplaceRenumber(oldToNew, from0ToAllFaces);
832 inplaceRenumber(oldToNew, from1ToAllFaces);
833}
834
835
836void Foam::polyMeshAdder::mergePointZones
837(
838 const label nAllPoints,
839 const pointZoneMesh& pz0,
840 const pointZoneMesh& pz1,
841 const labelList& from0ToAllPoints,
842 const labelList& from1ToAllPoints,
843
844 DynamicList<word>& zoneNames,
845 labelList& from1ToAll,
846 List<DynamicList<label>>& pzPoints
847)
848{
849 zoneNames.setCapacity(pz0.size() + pz1.size());
850 zoneNames.append(pz0.names());
851
852 from1ToAll.setSize(pz1.size());
853
854 forAll(pz1, zoneI)
855 {
856 from1ToAll[zoneI] = zoneIndex(pz1[zoneI].name(), zoneNames);
857 }
858 zoneNames.shrink();
859
860
861
862 // Zone(s) per point. Two levels: if only one zone
863 // stored in pointToZone. Any extra stored in additionalPointToZones.
864 // This is so we only allocate labelLists per point if absolutely
865 // necessary.
866 labelList pointToZone(nAllPoints, -1);
867 labelListList addPointToZones(nAllPoints);
868
869 // mesh0 zones kept
870 forAll(pz0, zoneI)
871 {
872 const pointZone& pz = pz0[zoneI];
873
874 forAll(pz, i)
875 {
876 label point0 = pz[i];
877 label allPointi = from0ToAllPoints[point0];
878
879 if (pointToZone[allPointi] == -1)
880 {
881 pointToZone[allPointi] = zoneI;
882 }
883 else if (pointToZone[allPointi] != zoneI)
884 {
885 addPointToZones[allPointi].push_uniq(zoneI);
886 }
887 }
888 }
889
890 // mesh1 zones renumbered
891 forAll(pz1, zoneI)
892 {
893 const pointZone& pz = pz1[zoneI];
894 const label allZoneI = from1ToAll[zoneI];
895
896 forAll(pz, i)
897 {
898 label point1 = pz[i];
899 label allPointi = from1ToAllPoints[point1];
900
901 if (pointToZone[allPointi] == -1)
902 {
903 pointToZone[allPointi] = allZoneI;
904 }
905 else if (pointToZone[allPointi] != allZoneI)
906 {
907 addPointToZones[allPointi].push_uniq(allZoneI);
908 }
909 }
910 }
911
912 // Extract back into zones
913
914 // 1. Count
915 labelList nPoints(zoneNames.size(), Zero);
916 forAll(pointToZone, allPointi)
917 {
918 label zoneI = pointToZone[allPointi];
919 if (zoneI != -1)
920 {
921 nPoints[zoneI]++;
922 }
923 }
924 forAll(addPointToZones, allPointi)
925 {
926 const labelList& pZones = addPointToZones[allPointi];
927 forAll(pZones, i)
928 {
929 nPoints[pZones[i]]++;
930 }
931 }
932
933 // 2. Fill
934 pzPoints.setSize(zoneNames.size());
935 forAll(pzPoints, zoneI)
936 {
937 pzPoints[zoneI].setCapacity(nPoints[zoneI]);
938 }
939 forAll(pointToZone, allPointi)
940 {
941 label zoneI = pointToZone[allPointi];
942 if (zoneI != -1)
943 {
944 pzPoints[zoneI].append(allPointi);
945 }
946 }
947 forAll(addPointToZones, allPointi)
948 {
949 const labelList& pZones = addPointToZones[allPointi];
950 forAll(pZones, i)
951 {
952 pzPoints[pZones[i]].append(allPointi);
953 }
954 }
955 forAll(pzPoints, i)
956 {
957 pzPoints[i].shrink();
958 stableSort(pzPoints[i]);
959 }
960}
961
962
963void Foam::polyMeshAdder::mergeFaceZones
964(
965 const labelList& allOwner,
966
967 const polyMesh& mesh0,
968 const polyMesh& mesh1,
969
970 const labelList& from0ToAllFaces,
971 const labelList& from1ToAllFaces,
972
973 const labelList& from1ToAllCells,
974
975 DynamicList<word>& zoneNames,
976 labelList& from1ToAll,
977 List<DynamicList<label>>& fzFaces,
978 List<DynamicList<bool>>& fzFlips
979)
980{
981 const faceZoneMesh& fz0 = mesh0.faceZones();
982 const labelList& owner0 = mesh0.faceOwner();
983 const faceZoneMesh& fz1 = mesh1.faceZones();
984 const labelList& owner1 = mesh1.faceOwner();
985
986
987 zoneNames.setCapacity(fz0.size() + fz1.size());
988 zoneNames.append(fz0.names());
989
990 from1ToAll.setSize(fz1.size());
991
992 forAll(fz1, zoneI)
993 {
994 from1ToAll[zoneI] = zoneIndex(fz1[zoneI].name(), zoneNames);
995 }
996 zoneNames.shrink();
997
998
999 // Zone(s) per face
1000 labelList faceToZone(allOwner.size(), -1);
1001 labelListList addFaceToZones(allOwner.size());
1002 boolList faceToFlip(allOwner.size(), false);
1003 boolListList addFaceToFlips(allOwner.size());
1004
1005 // mesh0 zones kept
1006 forAll(fz0, zoneI)
1007 {
1008 const labelList& addressing = fz0[zoneI];
1009 const boolList& flipMap = fz0[zoneI].flipMap();
1010
1011 forAll(addressing, i)
1012 {
1013 label face0 = addressing[i];
1014 bool flip0 = flipMap[i];
1015
1016 label allFacei = from0ToAllFaces[face0];
1017 if (allFacei != -1)
1018 {
1019 // Check if orientation same
1020 label allCell0 = owner0[face0];
1021 if (allOwner[allFacei] != allCell0)
1022 {
1023 flip0 = !flip0;
1024 }
1025
1026 if (faceToZone[allFacei] == -1)
1027 {
1028 faceToZone[allFacei] = zoneI;
1029 faceToFlip[allFacei] = flip0;
1030 }
1031 else if (faceToZone[allFacei] != zoneI)
1032 {
1033 if (addFaceToZones[allFacei].push_uniq(zoneI))
1034 {
1035 addFaceToFlips[allFacei].push_back(flip0);
1036 }
1037 }
1038 }
1039 }
1040 }
1041
1042 // mesh1 zones renumbered
1043 forAll(fz1, zoneI)
1044 {
1045 const labelList& addressing = fz1[zoneI];
1046 const boolList& flipMap = fz1[zoneI].flipMap();
1047
1048 const label allZoneI = from1ToAll[zoneI];
1049
1050 forAll(addressing, i)
1051 {
1052 label face1 = addressing[i];
1053 bool flip1 = flipMap[i];
1054
1055 label allFacei = from1ToAllFaces[face1];
1056 if (allFacei != -1)
1057 {
1058 // Check if orientation same
1059 label allCell1 = from1ToAllCells[owner1[face1]];
1060 if (allOwner[allFacei] != allCell1)
1061 {
1062 flip1 = !flip1;
1063 }
1064
1065 if (faceToZone[allFacei] == -1)
1066 {
1067 faceToZone[allFacei] = allZoneI;
1068 faceToFlip[allFacei] = flip1;
1069 }
1070 else if (faceToZone[allFacei] != allZoneI)
1071 {
1072 if (addFaceToZones[allFacei].push_uniq(allZoneI))
1073 {
1074 addFaceToFlips[allFacei].push_back(flip1);
1075 }
1076 }
1077 }
1078 }
1079 }
1080
1081
1082 // Extract back into zones
1083
1084 // 1. Count
1085 labelList nFaces(zoneNames.size(), Zero);
1086 forAll(faceToZone, allFacei)
1087 {
1088 label zoneI = faceToZone[allFacei];
1089 if (zoneI != -1)
1090 {
1091 nFaces[zoneI]++;
1092 }
1093 }
1094 forAll(addFaceToZones, allFacei)
1095 {
1096 const labelList& fZones = addFaceToZones[allFacei];
1097 forAll(fZones, i)
1098 {
1099 nFaces[fZones[i]]++;
1100 }
1101 }
1102
1103 // 2. Fill
1104 fzFaces.setSize(zoneNames.size());
1105 fzFlips.setSize(zoneNames.size());
1106 forAll(fzFaces, zoneI)
1107 {
1108 fzFaces[zoneI].setCapacity(nFaces[zoneI]);
1109 fzFlips[zoneI].setCapacity(nFaces[zoneI]);
1110 }
1111 forAll(faceToZone, allFacei)
1112 {
1113 label zoneI = faceToZone[allFacei];
1114 bool flip = faceToFlip[allFacei];
1115 if (zoneI != -1)
1116 {
1117 fzFaces[zoneI].append(allFacei);
1118 fzFlips[zoneI].append(flip);
1119 }
1120 }
1121 forAll(addFaceToZones, allFacei)
1122 {
1123 const labelList& fZones = addFaceToZones[allFacei];
1124 const boolList& flipZones = addFaceToFlips[allFacei];
1125
1126 forAll(fZones, i)
1127 {
1128 label zoneI = fZones[i];
1129 fzFaces[zoneI].append(allFacei);
1130 fzFlips[zoneI].append(flipZones[i]);
1131 }
1132 }
1133
1134 forAll(fzFaces, i)
1135 {
1136 fzFaces[i].shrink();
1137 fzFlips[i].shrink();
1138
1139 labelList order(sortedOrder(fzFaces[i]));
1140
1141 fzFaces[i] = labelUIndList(fzFaces[i], order)();
1142 fzFlips[i] = boolUIndList(fzFlips[i], order)();
1143 }
1144}
1145
1146
1147void Foam::polyMeshAdder::mergeCellZones
1148(
1149 const label nAllCells,
1150
1151 const cellZoneMesh& cz0,
1152 const cellZoneMesh& cz1,
1153 const labelList& from1ToAllCells,
1154
1155 DynamicList<word>& zoneNames,
1156 labelList& from1ToAll,
1157 List<DynamicList<label>>& czCells
1158)
1159{
1160 zoneNames.setCapacity(cz0.size() + cz1.size());
1161 zoneNames.append(cz0.names());
1162
1163 from1ToAll.setSize(cz1.size());
1164 forAll(cz1, zoneI)
1165 {
1166 from1ToAll[zoneI] = zoneIndex(cz1[zoneI].name(), zoneNames);
1167 }
1168 zoneNames.shrink();
1169
1170
1171 // Zone(s) per cell. Two levels: if only one zone
1172 // stored in cellToZone. Any extra stored in additionalCellToZones.
1173 // This is so we only allocate labelLists per cell if absolutely
1174 // necessary.
1175 labelList cellToZone(nAllCells, -1);
1176 labelListList addCellToZones(nAllCells);
1177
1178 // mesh0 zones kept
1179 forAll(cz0, zoneI)
1180 {
1181 const cellZone& cz = cz0[zoneI];
1182 forAll(cz, i)
1183 {
1184 label cell0 = cz[i];
1185
1186 if (cellToZone[cell0] == -1)
1187 {
1188 cellToZone[cell0] = zoneI;
1189 }
1190 else if (cellToZone[cell0] != zoneI)
1191 {
1192 addCellToZones[cell0].push_uniq(zoneI);
1193 }
1194 }
1195 }
1196
1197 // mesh1 zones renumbered
1198 forAll(cz1, zoneI)
1199 {
1200 const cellZone& cz = cz1[zoneI];
1201 const label allZoneI = from1ToAll[zoneI];
1202 forAll(cz, i)
1203 {
1204 label cell1 = cz[i];
1205 label allCelli = from1ToAllCells[cell1];
1206
1207 if (cellToZone[allCelli] == -1)
1208 {
1209 cellToZone[allCelli] = allZoneI;
1210 }
1211 else if (cellToZone[allCelli] != allZoneI)
1212 {
1213 addCellToZones[allCelli].push_uniq(allZoneI);
1214 }
1215 }
1216 }
1217
1218 // Extract back into zones
1219
1220 // 1. Count
1221 labelList nCells(zoneNames.size(), Zero);
1222 forAll(cellToZone, allCelli)
1223 {
1224 label zoneI = cellToZone[allCelli];
1225 if (zoneI != -1)
1226 {
1227 nCells[zoneI]++;
1228 }
1229 }
1230 forAll(addCellToZones, allCelli)
1231 {
1232 const labelList& cZones = addCellToZones[allCelli];
1233 forAll(cZones, i)
1234 {
1235 nCells[cZones[i]]++;
1236 }
1237 }
1238
1239 // 2. Fill
1240 czCells.setSize(zoneNames.size());
1241 forAll(czCells, zoneI)
1242 {
1243 czCells[zoneI].setCapacity(nCells[zoneI]);
1244 }
1245 forAll(cellToZone, allCelli)
1246 {
1247 label zoneI = cellToZone[allCelli];
1248 if (zoneI != -1)
1249 {
1250 czCells[zoneI].append(allCelli);
1251 }
1252 }
1253 forAll(addCellToZones, allCelli)
1254 {
1255 const labelList& cZones = addCellToZones[allCelli];
1256 forAll(cZones, i)
1257 {
1258 czCells[cZones[i]].append(allCelli);
1259 }
1260 }
1261 forAll(czCells, i)
1262 {
1263 czCells[i].shrink();
1264 stableSort(czCells[i]);
1265 }
1266}
1267
1268
1269void Foam::polyMeshAdder::mergeZones
1270(
1271 const label nAllPoints,
1272 const labelList& allOwner,
1273 const label nAllCells,
1274
1275 const polyMesh& mesh0,
1276 const polyMesh& mesh1,
1277 const labelList& from0ToAllPoints,
1278 const labelList& from0ToAllFaces,
1279
1280 const labelList& from1ToAllPoints,
1281 const labelList& from1ToAllFaces,
1282 const labelList& from1ToAllCells,
1283
1284 DynamicList<word>& pointZoneNames,
1285 List<DynamicList<label>>& pzPoints,
1286
1287 DynamicList<word>& faceZoneNames,
1288 List<DynamicList<label>>& fzFaces,
1289 List<DynamicList<bool>>& fzFlips,
1290
1291 DynamicList<word>& cellZoneNames,
1292 List<DynamicList<label>>& czCells
1293)
1294{
1295 labelList from1ToAllPZones;
1296 mergePointZones
1297 (
1298 nAllPoints,
1299 mesh0.pointZones(),
1300 mesh1.pointZones(),
1301 from0ToAllPoints,
1302 from1ToAllPoints,
1303
1304 pointZoneNames,
1305 from1ToAllPZones,
1306 pzPoints
1307 );
1308
1309 labelList from1ToAllFZones;
1310 mergeFaceZones
1311 (
1312 allOwner,
1313 mesh0,
1314 mesh1,
1315 from0ToAllFaces,
1316 from1ToAllFaces,
1317 from1ToAllCells,
1318
1319 faceZoneNames,
1320 from1ToAllFZones,
1321 fzFaces,
1322 fzFlips
1323 );
1324
1325 labelList from1ToAllCZones;
1326 mergeCellZones
1327 (
1328 nAllCells,
1329 mesh0.cellZones(),
1330 mesh1.cellZones(),
1331 from1ToAllCells,
1332
1333 cellZoneNames,
1334 from1ToAllCZones,
1335 czCells
1336 );
1337}
1338
1339
1340void Foam::polyMeshAdder::addZones
1341(
1342 const UList<word>& pointZoneNames,
1343 const List<DynamicList<label>>& pzPoints,
1344
1345 const UList<word>& faceZoneNames,
1346 const List<DynamicList<label>>& fzFaces,
1347 const List<DynamicList<bool>>& fzFlips,
1348
1349 const UList<word>& cellZoneNames,
1350 const List<DynamicList<label>>& czCells,
1351
1352 polyMesh& mesh
1353)
1354{
1355 List<pointZone*> pZones(pzPoints.size());
1356 forAll(pZones, i)
1357 {
1358 pZones[i] = new pointZone
1359 (
1360 pointZoneNames[i],
1361 pzPoints[i],
1362 i,
1364 );
1365 }
1366
1367 List<faceZone*> fZones(fzFaces.size());
1368 forAll(fZones, i)
1369 {
1370 fZones[i] = new faceZone
1371 (
1372 faceZoneNames[i],
1373 fzFaces[i],
1374 fzFlips[i],
1375 i,
1376 mesh.faceZones()
1377 );
1378 }
1379
1380 List<cellZone*> cZones(czCells.size());
1381 forAll(cZones, i)
1382 {
1383 cZones[i] = new cellZone
1384 (
1385 cellZoneNames[i],
1386 czCells[i],
1387 i,
1388 mesh.cellZones()
1389 );
1390 }
1391
1393 (
1394 pZones,
1395 fZones,
1396 cZones
1397 );
1398}
1399
1400
1402// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1403
1404// Returns new mesh and sets
1405// - map from new cell/face/point/patch to either mesh0 or mesh1
1406//
1407// mesh0Faces/mesh1Faces: corresponding faces on both meshes.
1409(
1410 const IOobject& io,
1411 const polyMesh& mesh0,
1412 const polyMesh& mesh1,
1413 const faceCoupleInfo& coupleInfo,
1415)
1416{
1417 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1418 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1419
1420
1421 DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1422 DynamicList<word> allPatchTypes(allPatchNames.size());
1423
1424 // Patch maps
1425 labelList from1ToAllPatches(patches1.size());
1426 labelList fromAllTo1Patches(allPatchNames.size(), -1);
1427
1428 mergePatchNames
1429 (
1430 patches0,
1431 patches1,
1432 allPatchNames,
1433 allPatchTypes,
1434 from1ToAllPatches,
1435 fromAllTo1Patches
1436 );
1437
1438
1439 // New points
1440 pointField allPoints;
1441
1442 // Map from mesh0/1 points to allPoints.
1443 labelList from0ToAllPoints(mesh0.nPoints(), -1);
1444 labelList from1ToAllPoints(mesh1.nPoints(), -1);
1445
1446 // New faces
1447 faceList allFaces;
1448 label nInternalFaces;
1449
1450 // New cells
1451 labelList allOwner;
1452 labelList allNeighbour;
1453 label nCells;
1454
1455 // Sizes per patch
1456 labelList nFaces(allPatchNames.size(), Zero);
1457
1458 // Maps
1459 labelList from0ToAllFaces(mesh0.nFaces(), -1);
1460 labelList from1ToAllFaces(mesh1.nFaces(), -1);
1461
1462 // Map
1463 labelList from1ToAllCells(mesh1.nCells(), -1);
1464
1465 mergePrimitives
1466 (
1467 mesh0,
1468 mesh1,
1469 coupleInfo,
1470
1471 allPatchNames.size(),
1472 fromAllTo1Patches,
1473 from1ToAllPatches,
1474
1475 allPoints,
1476 from0ToAllPoints,
1477 from1ToAllPoints,
1478
1479 allFaces,
1480 allOwner,
1481 allNeighbour,
1482 nInternalFaces,
1483 nFaces,
1484 nCells,
1485
1486 from0ToAllFaces,
1487 from1ToAllFaces,
1488 from1ToAllCells
1489 );
1490
1491
1492 // Zones
1493 // ~~~~~
1494
1495 DynamicList<word> pointZoneNames;
1496 List<DynamicList<label>> pzPoints;
1497
1498 DynamicList<word> faceZoneNames;
1499 List<DynamicList<label>> fzFaces;
1500 List<DynamicList<bool>> fzFlips;
1501
1502 DynamicList<word> cellZoneNames;
1503 List<DynamicList<label>> czCells;
1504
1505 mergeZones
1506 (
1507 allPoints.size(),
1508 allOwner,
1509 nCells,
1510
1511 mesh0,
1512 mesh1,
1513
1514 from0ToAllPoints,
1515 from0ToAllFaces,
1516
1517 from1ToAllPoints,
1518 from1ToAllFaces,
1519 from1ToAllCells,
1520
1521 pointZoneNames,
1522 pzPoints,
1523
1524 faceZoneNames,
1525 fzFaces,
1526 fzFlips,
1527
1528 cellZoneNames,
1529 czCells
1530 );
1531
1532
1533 // Patches
1534 // ~~~~~~~
1535
1536 // Map from 0 to all patches (since gets compacted)
1537 labelList from0ToAllPatches(patches0.size(), -1);
1538
1539 List<polyPatch*> allPatches
1540 (
1541 combinePatches
1542 (
1543 mesh0,
1544 mesh1,
1545 patches0, // Should be boundaryMesh() on new mesh.
1546 allPatchNames.size(),
1547 fromAllTo1Patches,
1548 mesh0.nInternalFaces()
1549 + mesh1.nInternalFaces()
1550 + coupleInfo.cutFaces().size(),
1551 nFaces,
1552
1553 from0ToAllPatches,
1554 from1ToAllPatches
1555 )
1556 );
1557
1558
1559 // Map information
1560 // ~~~~~~~~~~~~~~~
1561
1562 mapPtr.reset
1563 (
1565 (
1566 mesh0.nPoints(),
1567 mesh0.nFaces(),
1568 mesh0.nCells(),
1569
1570 mesh1.nPoints(),
1571 mesh1.nFaces(),
1572 mesh1.nCells(),
1573
1574 from0ToAllPoints,
1575 from0ToAllFaces,
1576 identity(mesh0.nCells()),
1577
1578 from1ToAllPoints,
1579 from1ToAllFaces,
1580 from1ToAllCells,
1581
1582 from0ToAllPatches,
1583 from1ToAllPatches,
1584 patches0.patchSizes(),
1585 patches0.patchStarts()
1586 )
1587 );
1588
1589
1590
1591 // Now we have extracted all information from all meshes.
1592 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1593
1594 // Construct mesh
1596 (
1597 io,
1598 std::move(allPoints),
1599 std::move(allFaces),
1600 std::move(allOwner),
1601 std::move(allNeighbour)
1602 );
1603 polyMesh& mesh = *meshPtr;
1604
1605 // Add zones to new mesh.
1606 addZones
1607 (
1608 pointZoneNames,
1609 pzPoints,
1610
1611 faceZoneNames,
1612 fzFaces,
1613 fzFlips,
1614
1615 cellZoneNames,
1616 czCells,
1617 mesh
1618 );
1619
1620 // Add patches to new mesh
1621 mesh.addPatches(allPatches);
1622
1623 return meshPtr;
1624}
1625
1626
1627// Inplace add mesh1 to mesh0
1629(
1630 polyMesh& mesh0,
1631 const polyMesh& mesh1,
1632 const faceCoupleInfo& coupleInfo,
1633 const bool validBoundary
1634)
1635{
1636 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1637 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1638
1639 DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1640 DynamicList<word> allPatchTypes(allPatchNames.size());
1641
1642 // Patch maps
1643 labelList from1ToAllPatches(patches1.size());
1644 labelList fromAllTo1Patches(allPatchNames.size(), -1);
1645
1646 mergePatchNames
1647 (
1648 patches0,
1649 patches1,
1650 allPatchNames,
1651 allPatchTypes,
1652 from1ToAllPatches,
1653 fromAllTo1Patches
1654 );
1655
1656
1657 // New points
1658 pointField allPoints;
1659
1660 // Map from mesh0/1 points to allPoints.
1661 labelList from0ToAllPoints(mesh0.nPoints(), -1);
1662 labelList from1ToAllPoints(mesh1.nPoints(), -1);
1663
1664 // New faces
1665 faceList allFaces;
1666 labelList allOwner;
1667 labelList allNeighbour;
1668 label nInternalFaces;
1669 // Sizes per patch
1670 labelList nFaces(allPatchNames.size(), Zero);
1671 label nCells;
1672
1673 // Maps
1674 labelList from0ToAllFaces(mesh0.nFaces(), -1);
1675 labelList from1ToAllFaces(mesh1.nFaces(), -1);
1676 // Map
1677 labelList from1ToAllCells(mesh1.nCells(), -1);
1678
1679 mergePrimitives
1680 (
1681 mesh0,
1682 mesh1,
1683 coupleInfo,
1684
1685 allPatchNames.size(),
1686 fromAllTo1Patches,
1687 from1ToAllPatches,
1688
1689 allPoints,
1690 from0ToAllPoints,
1691 from1ToAllPoints,
1692
1693 allFaces,
1694 allOwner,
1695 allNeighbour,
1696 nInternalFaces,
1697 nFaces,
1698 nCells,
1699
1700 from0ToAllFaces,
1701 from1ToAllFaces,
1702 from1ToAllCells
1703 );
1704
1705
1706 // Zones
1707 // ~~~~~
1708
1709 DynamicList<word> pointZoneNames;
1710 List<DynamicList<label>> pzPoints;
1711
1712 DynamicList<word> faceZoneNames;
1713 List<DynamicList<label>> fzFaces;
1714 List<DynamicList<bool>> fzFlips;
1715
1716 DynamicList<word> cellZoneNames;
1717 List<DynamicList<label>> czCells;
1718
1719 mergeZones
1720 (
1721 allPoints.size(),
1722 allOwner,
1723 nCells,
1724
1725 mesh0,
1726 mesh1,
1727
1728 from0ToAllPoints,
1729 from0ToAllFaces,
1730
1731 from1ToAllPoints,
1732 from1ToAllFaces,
1733 from1ToAllCells,
1734
1735 pointZoneNames,
1736 pzPoints,
1737
1738 faceZoneNames,
1739 fzFaces,
1740 fzFlips,
1741
1742 cellZoneNames,
1743 czCells
1744 );
1745
1746
1747 // Patches
1748 // ~~~~~~~
1749
1750
1751 // Store mesh0 patch info before modifying patches0.
1752 labelList mesh0PatchSizes(patches0.patchSizes());
1753 labelList mesh0PatchStarts(patches0.patchStarts());
1754
1755 // Map from 0 to all patches (since gets compacted)
1756 labelList from0ToAllPatches(patches0.size(), -1);
1757
1758 // Inplace extend mesh0 patches (note that patches0.size() now also
1759 // has changed)
1760 polyBoundaryMesh& allPatches =
1761 const_cast<polyBoundaryMesh&>(mesh0.boundaryMesh());
1762 allPatches.setSize(allPatchNames.size());
1763 labelList patchSizes(allPatches.size());
1764 labelList patchStarts(allPatches.size());
1765
1766 label startFacei = nInternalFaces;
1767
1768 // Copy patches0 with new sizes. First patches always come from
1769 // mesh0 and will always be present.
1770 label allPatchi = 0;
1771
1772 forAll(from0ToAllPatches, patch0)
1773 {
1774 // Originates from mesh0. Clone with new size & filter out empty
1775 // patch.
1776
1777 if (nFaces[patch0] == 0 && isA<processorPolyPatch>(allPatches[patch0]))
1778 {
1779 //Pout<< "Removing zero sized mesh0 patch " << allPatchNames[patch0]
1780 // << endl;
1781 from0ToAllPatches[patch0] = -1;
1782 // Check if patch was also in mesh1 and update its addressing if so.
1783 if (fromAllTo1Patches[patch0] != -1)
1784 {
1785 from1ToAllPatches[fromAllTo1Patches[patch0]] = -1;
1786 }
1787 }
1788 else
1789 {
1790 // Clone. Note dummy size and start. Gets overwritten later in
1791 // resetPrimitives. This avoids getting temporarily illegal
1792 // SubList construction in polyPatch.
1793 allPatches.set
1794 (
1795 allPatchi,
1796 allPatches[patch0].clone
1797 (
1798 allPatches,
1799 allPatchi,
1800 0, // dummy size
1801 0 // dummy start
1802 )
1803 );
1804 patchSizes[allPatchi] = nFaces[patch0];
1805 patchStarts[allPatchi] = startFacei;
1806
1807 // Record new index in allPatches
1808 from0ToAllPatches[patch0] = allPatchi;
1809
1810 // Check if patch was also in mesh1 and update its addressing if so.
1811 if (fromAllTo1Patches[patch0] != -1)
1812 {
1813 from1ToAllPatches[fromAllTo1Patches[patch0]] = allPatchi;
1814 }
1815
1816 startFacei += nFaces[patch0];
1817
1818 allPatchi++;
1819 }
1820 }
1821
1822 // Copy unique patches of mesh1.
1823 forAll(from1ToAllPatches, patch1)
1824 {
1825 label uncompactAllPatchi = from1ToAllPatches[patch1];
1826
1827 if (uncompactAllPatchi >= from0ToAllPatches.size())
1828 {
1829 // Patch has not been merged with any mesh0 patch.
1830
1831 if
1832 (
1833 nFaces[uncompactAllPatchi] == 0
1834 && isA<processorPolyPatch>(patches1[patch1])
1835 )
1836 {
1837 //Pout<< "Removing zero sized mesh1 patch "
1838 // << allPatchNames[uncompactAllPatchi] << endl;
1839 from1ToAllPatches[patch1] = -1;
1840 }
1841 else
1842 {
1843 // Clone.
1844 allPatches.set
1845 (
1846 allPatchi,
1847 patches1[patch1].clone
1848 (
1849 allPatches,
1850 allPatchi,
1851 0, // dummy size
1852 0 // dummy start
1853 )
1854 );
1855 patchSizes[allPatchi] = nFaces[uncompactAllPatchi];
1856 patchStarts[allPatchi] = startFacei;
1857
1858 // Record new index in allPatches
1859 from1ToAllPatches[patch1] = allPatchi;
1860
1861 startFacei += nFaces[uncompactAllPatchi];
1862
1863 allPatchi++;
1864 }
1865 }
1866 }
1867
1868 allPatches.setSize(allPatchi);
1869 patchSizes.setSize(allPatchi);
1870 patchStarts.setSize(allPatchi);
1871
1872
1873 // Construct map information before changing mesh0 primitives
1874 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1875
1877 (
1879 (
1880 mesh0.nPoints(),
1881 mesh0.nFaces(),
1882 mesh0.nCells(),
1883
1884 mesh1.nPoints(),
1885 mesh1.nFaces(),
1886 mesh1.nCells(),
1887
1888 from0ToAllPoints,
1889 from0ToAllFaces,
1890 identity(mesh0.nCells()),
1891
1892 from1ToAllPoints,
1893 from1ToAllFaces,
1894 from1ToAllCells,
1895
1896 from0ToAllPatches,
1897 from1ToAllPatches,
1898
1899 mesh0PatchSizes,
1900 mesh0PatchStarts
1901 )
1902 );
1903
1904
1905
1906 // Now we have extracted all information from all meshes.
1907 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1908
1909 mesh0.resetMotion(); // delete any oldPoints.
1910 mesh0.resetPrimitives
1911 (
1912 autoPtr<pointField>::New(std::move(allPoints)),
1913 autoPtr<faceList>::New(std::move(allFaces)),
1914 autoPtr<labelList>::New(std::move(allOwner)),
1915 autoPtr<labelList>::New(std::move(allNeighbour)),
1916 patchSizes, // size
1917 patchStarts, // patchstarts
1918 validBoundary // boundary valid?
1919 );
1920
1921 // Add zones to new mesh.
1922 mesh0.pointZones().clear();
1923 mesh0.faceZones().clear();
1924 mesh0.cellZones().clear();
1925 addZones
1926 (
1927 pointZoneNames,
1928 pzPoints,
1929
1930 faceZoneNames,
1931 fzFaces,
1932 fzFlips,
1933
1934 cellZoneNames,
1935 czCells,
1936 mesh0
1937 );
1938
1939 return mapPtr;
1940}
1941
1942
1944(
1945 const polyMesh& mesh,
1946 const scalar mergeDist
1947)
1948{
1949 const labelList& sharedPointLabels = mesh.globalData().sharedPointLabels();
1950 const labelList& sharedPointAddr = mesh.globalData().sharedPointAddr();
1951
1952 // Because of adding the missing pieces e.g. when redistributing a mesh
1953 // it can be that there are multiple points on the same processor that
1954 // refer to the same shared point.
1955
1956 // Invert point-to-shared addressing
1957 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1958
1959 Map<labelList> sharedToMesh(sharedPointLabels.size());
1960
1961 label nMultiple = 0;
1962
1963 forAll(sharedPointLabels, i)
1964 {
1965 label pointi = sharedPointLabels[i];
1966
1967 label sharedI = sharedPointAddr[i];
1968
1969 auto iter = sharedToMesh.find(sharedI);
1970
1971 if (iter.good())
1972 {
1973 // sharedI already used by other point. Add this one.
1974
1975 nMultiple++;
1976
1977 labelList& connectedPointLabels = iter.val();
1978
1979 label sz = connectedPointLabels.size();
1980
1981 // Check just to make sure.
1982 if (connectedPointLabels.found(pointi))
1983 {
1985 << "Duplicate point in sharedPoint addressing." << endl
1986 << "When trying to add point " << pointi << " on shared "
1987 << sharedI << " with connected points "
1988 << connectedPointLabels
1989 << abort(FatalError);
1990 }
1991
1992 connectedPointLabels.setSize(sz+1);
1993 connectedPointLabels[sz] = pointi;
1994 }
1995 else
1996 {
1997 sharedToMesh.insert(sharedI, labelList(1, pointi));
1998 }
1999 }
2000
2001
2002 // Assign single master for every shared with multiple geometric points
2003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2004
2005 Map<label> pointToMaster(nMultiple);
2006
2007 forAllConstIters(sharedToMesh, iter)
2008 {
2009 const labelList& connectedPointLabels = iter.val();
2010
2011 //Pout<< "For shared:" << iter.key()
2012 // << " found points:" << connectedPointLabels
2013 // << " at coords:"
2014 // << pointField(mesh.points(), connectedPointLabels) << endl;
2015
2016 if (connectedPointLabels.size() > 1)
2017 {
2018 const pointField connectedPoints
2019 (
2020 mesh.points(),
2021 connectedPointLabels
2022 );
2023
2024 labelList toMergedPoints;
2025 label nUnique = Foam::mergePoints
2026 (
2027 connectedPoints,
2028 mergeDist,
2029 false,
2030 toMergedPoints
2031 );
2032
2033 if (nUnique < connectedPoints.size())
2034 {
2035 // Invert toMergedPoints
2036 const labelListList mergeSets
2037 (
2039 (
2040 nUnique,
2041 toMergedPoints
2042 )
2043 );
2044
2045 // Find master for valid merges
2046 forAll(mergeSets, setI)
2047 {
2048 const labelList& mergeSet = mergeSets[setI];
2049
2050 if (mergeSet.size() > 1)
2051 {
2052 // Pick lowest numbered point
2053 label masterPointi = labelMax;
2054
2055 forAll(mergeSet, i)
2056 {
2057 label pointi = connectedPointLabels[mergeSet[i]];
2058
2059 masterPointi = min(masterPointi, pointi);
2060 }
2061
2062 forAll(mergeSet, i)
2063 {
2064 label pointi = connectedPointLabels[mergeSet[i]];
2065
2066 //Pout<< "Merging point " << pointi
2067 // << " at " << mesh.points()[pointi]
2068 // << " into master point " << masterPointi
2069 // << " at " << mesh.points()[masterPointi]
2070 // << endl;
2071
2072 pointToMaster.insert(pointi, masterPointi);
2073 }
2074 }
2075 }
2076 }
2077 }
2078 }
2079
2080 //- Old: geometric merging. Causes problems for two close shared points.
2081 //labelList sharedToMerged;
2082 //label nUnique = Foam::mergePoints
2083 //(
2084 // UIndirectList<point>(mesh.points(), sharedPointLabels),
2085 // mergeDist,
2086 // false,
2087 // sharedToMerged
2088 //);
2089 //
2092 //
2093 //Map<label> pointToMaster(10*sharedToMerged.size());
2094 //
2095 //if (nUnique < sharedPointLabels.size())
2096 //{
2097 // labelListList mergeSets
2098 // (
2099 // invertOneToMany
2100 // (
2101 // sharedToMerged.size(),
2102 // sharedToMerged
2103 // )
2104 // );
2105 //
2106 // label nMergeSets = 0;
2107 //
2108 // forAll(mergeSets, setI)
2109 // {
2110 // const labelList& mergeSet = mergeSets[setI];
2111 //
2112 // if (mergeSet.size() > 1)
2113 // {
2114 // // Take as master the shared point with the lowest mesh
2115 // // point label. (rather arbitrarily - could use max or
2116 // // any other one of the points)
2117 //
2118 // nMergeSets++;
2119 //
2120 // label masterI = labelMax;
2121 //
2122 // forAll(mergeSet, i)
2123 // {
2124 // label sharedI = mergeSet[i];
2125 //
2126 // masterI = min(masterI, sharedPointLabels[sharedI]);
2127 // }
2128 //
2129 // forAll(mergeSet, i)
2130 // {
2131 // label sharedI = mergeSet[i];
2132 //
2133 // pointToMaster.insert(sharedPointLabels[sharedI], masterI);
2134 // }
2135 // }
2136 // }
2137 //
2138 // //if (debug)
2139 // //{
2140 // // Pout<< "polyMeshAdder : merging:"
2141 // // << pointToMaster.size() << " into " << nMergeSets
2142 // // << " sets." << endl;
2143 // //}
2144 //}
2145
2146 return pointToMaster;
2147}
2148
2149
2151(
2152 const polyMesh& mesh,
2153 const Map<label>& pointToMaster,
2154 polyTopoChange& meshMod
2155)
2156{
2157 // Remove all non-master points.
2158 forAll(mesh.points(), pointi)
2159 {
2160 const auto iter = pointToMaster.cfind(pointi);
2161
2162 if (iter.good())
2163 {
2164 if (iter.val() != pointi)
2165 {
2166 meshMod.removePoint(pointi, iter.val());
2167 }
2168 }
2169 }
2170
2171 // Modify faces for points. Note: could use pointFaces here but want to
2172 // avoid addressing calculation.
2173 const faceList& faces = mesh.faces();
2174
2175 forAll(faces, facei)
2176 {
2177 const face& f = faces[facei];
2178
2179 bool hasMerged = false;
2180
2181 forAll(f, fp)
2182 {
2183 label pointi = f[fp];
2184
2185 const auto iter = pointToMaster.cfind(pointi);
2186
2187 if (iter.good())
2188 {
2189 if (iter.val() != pointi)
2190 {
2191 hasMerged = true;
2192 break;
2193 }
2194 }
2195 }
2196
2197 if (hasMerged)
2198 {
2199 face newF(f);
2200
2201 forAll(f, fp)
2202 {
2203 label pointi = f[fp];
2204
2205 const auto iter = pointToMaster.cfind(pointi);
2206
2207 if (iter.good())
2208 {
2209 newF[fp] = iter.val();
2210 }
2211 }
2212
2213 label patchID = mesh.boundaryMesh().whichPatch(facei);
2214 label nei = (patchID == -1 ? mesh.faceNeighbour()[facei] : -1);
2215 label zoneID = mesh.faceZones().whichZone(facei);
2216 bool zoneFlip = false;
2217
2218 if (zoneID >= 0)
2219 {
2220 const faceZone& fZone = mesh.faceZones()[zoneID];
2221 zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
2222 }
2223
2224 meshMod.setAction
2225 (
2227 (
2228 newF, // modified face
2229 facei, // label of face
2230 mesh.faceOwner()[facei], // owner
2231 nei, // neighbour
2232 false, // face flip
2233 patchID, // patch for face
2234 false, // remove from zone
2235 zoneID, // zone for face
2236 zoneFlip // face flip in zone
2237 )
2238 );
2239 }
2240 }
2241}
2242
2243
2244Foam::label Foam::polyMeshAdder::procPatchIndex
2245(
2246 const polyBoundaryMesh& pbm,
2247 const label nbrProci,
2248 const label n
2249)
2250{
2251 // Find n'th processor patch going to nbrProci. Usually n=0 but in some
2252 // cases (e.g. processorCyclic, implicit cht) there can be more than one
2253 // processor patch between two processors.
2254
2255 label index = n;
2256
2257 for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++)
2258 {
2259 const processorPolyPatch& pp =
2261 if (pp.neighbProcNo() == nbrProci)
2262 {
2263 if (index == 0)
2264 {
2265 return patchi;
2266 }
2267 else
2268 {
2269 --index;
2270 }
2271 }
2272 }
2273
2274 FatalErrorInFunction << "no patch found to processor " << nbrProci
2275 << ". Current patches:" << pbm.names() << exit(FatalError);
2276 return -1;
2277}
2278
2279
2281(
2283 List<DynamicList<label>>& localPatch,
2284 List<DynamicList<label>>& remoteProc,
2285 List<DynamicList<label>>& remotePatch
2286 //List<labelListList>& remotePatchFace,
2287 //List<labelListList>& remotePatchFaceStart
2288)
2289{
2290 // Determine pairs of processor patches:
2291 // - remote processor
2292 // - patch on remote processor
2293 // - face on remote patch
2294 // - starting index on remote face
2295 localPatch.setSize(meshes.size());
2296 remoteProc.setSize(meshes.size());
2297 remotePatch.setSize(meshes.size());
2298 //remotePatchFace.setSize(meshes.size());
2299 //remotePatchFaceStart.setSize(meshes.size());
2300
2301
2302 // Check that all processors have the same globalPatches
2303 {
2304 const polyBoundaryMesh& pbm = meshes[0].boundaryMesh();
2305 const wordList names0(SubList<word>(pbm.names(), pbm.nNonProcessor()));
2306 for (label proci = 1; proci < meshes.size(); proci++)
2307 {
2308 const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2309 const wordList names(pbm.names());
2310
2311 if (SubList<word>(names, pbm.nNonProcessor()) != names0)
2312 {
2314 << "Patch names should be identical on all processors."
2315 << " Processor 0 has " << names0
2316 << ". Processor " << proci
2317 << " has " << names
2318 << exit(FatalError);
2319 }
2320 }
2321 }
2322
2323
2324 // Work array
2325 labelList nNeighbourProcs(meshes.size());
2326
2327 forAll(meshes, proci)
2328 {
2329 const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2330
2331 // Running count of number of patches communicating with same nbr
2332 // (usually 0)
2333 nNeighbourProcs = 0;
2334
2335 for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++)
2336 {
2337 const processorPolyPatch& pp =
2339 if (pp.owner())
2340 {
2341 const label nbrProci = pp.neighbProcNo();
2342 const label nbrPatchi = procPatchIndex
2343 (
2344 meshes[nbrProci].boundaryMesh(),
2345 proci,
2346 nNeighbourProcs[nbrProci]
2347 );
2348
2349 const auto& nbrPbm = meshes[nbrProci].boundaryMesh();
2350 const auto& nbrPp = nbrPbm[nbrPatchi];
2351 if (pp.size() != nbrPp.size())
2352 {
2354 << "at proc:" << proci
2355 << " processor patch "
2356 << pp.name() << " is not same size " << pp.size()
2357 << " as coupled patch " << nbrPp.name()
2358 << " on proc:" << nbrProci
2359 << " size:" << nbrPp.size()
2360 << exit(FatalError);
2361 }
2362
2363 localPatch[proci].append(patchi);
2364 remoteProc[proci].append(nbrProci);
2365 remotePatch[proci].append(nbrPatchi);
2366
2367 localPatch[nbrProci].append(nbrPatchi);
2368 remoteProc[nbrProci].append(proci);
2369 remotePatch[nbrProci].append(patchi);
2370
2371 nNeighbourProcs[nbrProci]++;
2372 }
2373 }
2374 }
2375
2377 //forAll(meshes, proci)
2378 //{
2379 // const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2380 //
2381 // const DynamicList<label>& localPatches = localPatch[proci];
2382 //
2383 // labelListList& rpf = remotePatchFace[proci];
2384 // rpf.setSize(localPatches.size());
2385 //
2386 // labelListList& rps = remotePatchFaceStart[proci];
2387 // rps.setSize(localPatches.size());
2388 //
2389 // forAll(localPatches, i)
2390 // {
2391 // const auto& pp = pbm[localPatches[i]];
2392 // rpf[i] = identity(pp.size());
2393 // rps[i].setSize(pp.size(), 0);
2394 // }
2395 //}
2396
2397 return meshes[0].boundaryMesh().nNonProcessor();
2398}
2399
2400
2402(
2404 const List<DynamicList<label>>& localPatch,
2405 const List<DynamicList<label>>& remoteMesh,
2406 const List<DynamicList<label>>& remotePatch,
2407 labelListList& localBoundaryFace,
2408 labelListList& remoteFaceMesh,
2409 labelListList& remoteBoundaryFace
2410)
2411{
2412 // Calculates pairs of matching (boundary) faces. Returns
2413 // localBoundaryFace[meshi] : index of local face (in boundary face
2414 // indexing!)
2415 // remoteMesh[meshi] : index of remote mesh
2416 // remoteBoundaryFace[meshi] : index of remote face (in boundary face
2417 // indexing!)
2418 localBoundaryFace.setSize(meshes.size());
2419 remoteFaceMesh.setSize(meshes.size());
2420 remoteBoundaryFace.setSize(meshes.size());
2421
2422 forAll(meshes, meshi)
2423 {
2424 const auto& mesh = meshes[meshi];
2425 const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2426 const labelUList& procPatches = localPatch[meshi];
2427 const labelUList& procNbrs = remoteMesh[meshi];
2428 const labelUList& procNbrPatches = remotePatch[meshi];
2429
2430
2431 // Count number of processor faces
2432 label nFaces = 0;
2433 for (const label patchi : procPatches)
2434 {
2435 nFaces += pbm[patchi].size();
2436 }
2437
2438 labelList& procFaces = localBoundaryFace[meshi];
2439 labelList& remoteMeshes = remoteFaceMesh[meshi];
2440 labelList& remoteFaces = remoteBoundaryFace[meshi];
2441
2442 procFaces.setSize(nFaces);
2443 remoteMeshes.setSize(nFaces);
2444 remoteFaces.setSize(nFaces);
2445
2446 nFaces = 0;
2447
2448 forAll(procPatches, i)
2449 {
2450 const label patchi = procPatches[i];
2451 const label nbrMeshi = procNbrs[i];
2452 const label nbrPatchi = procNbrPatches[i];
2453
2454 const auto& pp = pbm[patchi];
2455 const label offset = pp.start()-mesh.nInternalFaces();
2456
2457 const auto& nbrMesh = meshes[nbrMeshi];
2458 const auto& nbrPp = nbrMesh.boundaryMesh()[nbrPatchi];
2459 const label nbrOffset = nbrPp.start()-nbrMesh.nInternalFaces();
2460
2461 forAll(pp, patchFacei)
2462 {
2463 procFaces[nFaces] = offset+patchFacei;
2464 remoteMeshes[nFaces] = nbrMeshi;
2465 remoteFaces[nFaces] = nbrOffset+patchFacei;
2466 nFaces++;
2467 }
2468 }
2469 }
2470}
2471
2472
2473void Foam::polyMeshAdder::compactPoints
2474(
2476 const labelListList& localBoundaryFace,
2477 const labelListList& remoteFaceMesh,
2478 const labelListList& remoteBoundaryFace,
2479 const labelListList& remoteFaceStart,
2481
2482 labelListList& pointProcAddressing,
2483 labelListList& localPoints
2484)
2485{
2486 // Determines 'master' points for shared points. Returns
2487 // pointProcAddressing[meshi] : global point for every mesh point
2488 // localPoints[meshi] : indices of local points that are unique
2489
2490 // Choose minimum point for shared ones. Iterate minimising global points
2491 // until nothing changes
2492 while (true)
2493 {
2494 label nChanged = 0;
2495 forAll(meshes, meshi)
2496 {
2497 if (meshes.set(meshi))
2498 {
2499 const polyMesh& mesh = meshes[meshi];
2500 const faceList& faces = mesh.faces();
2501
2502 labelList& pAddressing = pointProcAddressing[meshi];
2503
2504 const labelList& localBFaces = localBoundaryFace[meshi];
2505 const labelList& procNbrs = remoteFaceMesh[meshi];
2506 const labelList& procNbrBFaces = remoteBoundaryFace[meshi];
2507 const labelList& procNbrIndex = remoteFaceStart[meshi];
2508
2509 forAll(localBFaces, i)
2510 {
2511 const label bFacei = localBFaces[i];
2512 const label nbrMeshi = procNbrs[i];
2513 const label nbrBFacei = procNbrBFaces[i];
2514
2515 // Local mesh face
2516 const label facei = mesh.nInternalFaces()+bFacei;
2517 const face& f = faces[facei];
2518
2519 // Matched (remote) face
2520 const auto& nbrMesh = meshes[nbrMeshi];
2521 const label nbrFacei = nbrMesh.nInternalFaces()+nbrBFacei;
2522 const face& nbrF = nbrMesh.faces()[nbrFacei];
2523
2524
2525 labelList& nbrAddressing = pointProcAddressing[nbrMeshi];
2526
2527 // Starting index is indexed wrt matched, not original
2528 // face. Check!
2529 label nbrFp = procNbrIndex[i];
2530
2531 forAll(f, fp)
2532 {
2533 label& ppPointi = pAddressing[f[fp]];
2534 label& nbrPointi = nbrAddressing[nbrF[nbrFp]];
2535
2536 //const point& pt = mesh.points()[f[fp]];
2537 //const point& nbrPt = nbrMesh.points()[nbrF[nbrFp]];
2538 //if (mag(pt-nbrPt) > SMALL)
2539 //{
2540 // FatalErrorInFunction
2541 // << "Merging differing points :"
2542 // << " pt:" << pt
2543 // << " nbrPt:" << nbrPt
2544 // << exit(FatalError);
2545 //}
2546
2547 if (ppPointi < nbrPointi)
2548 {
2549 //Pout<< "on proc:" << nbrMeshi
2550 // << " point:" << nbrF[nbrFp]
2551 // << " changing from:" << nbrPointi
2552 // << " to:" << ppPointi << endl;
2553 nbrPointi = ppPointi;
2554 nChanged++;
2555 }
2556 else if (nbrPointi < ppPointi)
2557 {
2558 //Pout<< "on proc:" << meshi
2559 // << " point:" << f[fp]
2560 // << " changing from:" << ppPointi
2561 // << " to:" << nbrPointi << endl;
2562 ppPointi = nbrPointi;
2563 nChanged++;
2564 }
2565
2566 nbrFp = nbrF.rcIndex(nbrFp);
2567 }
2568 }
2569 }
2570 }
2571
2572 if (nChanged == 0)
2573 {
2574 break;
2575 }
2576 }
2577
2578
2579
2580 // Compact out unused points
2581 localPoints.setSize(meshes.size());
2582 labelList globalToCompact(globalPoints.totalSize(), -1);
2583 label nGlobal = 0;
2584 forAll(meshes, meshi)
2585 {
2586 if (meshes.set(meshi))
2587 {
2588 const polyMesh& mesh = meshes[meshi];
2589
2590 labelList& compactPoints = localPoints[meshi];
2591 compactPoints.setSize(mesh.nPoints());
2592 label nCompact = 0;
2593
2594 const labelList& pAddressing = pointProcAddressing[meshi];
2595 forAll(pAddressing, pointi)
2596 {
2597 //Pout<< "proc:" << meshi
2598 // << " localpoint:" << pointi
2599 // << " globalpoint:"
2600 // << globalPoints.toGlobal(meshi, pointi)
2601 // << " merged:" << pAddressing[pointi]
2602 // << endl;
2603
2604 const label globali = globalPoints.toGlobal(meshi, pointi);
2605
2606 if (pAddressing[pointi] == globali)
2607 {
2608 // Unchanged address
2609 globalToCompact[globali] = nGlobal++;
2610 compactPoints[nCompact++] = pointi;
2611 }
2612 }
2613 compactPoints.setSize(nCompact);
2614 }
2615 }
2616
2617 forAll(meshes, meshi)
2618 {
2619 labelList& pAddressing = pointProcAddressing[meshi];
2620 pAddressing = UIndirectList<label>(globalToCompact, pAddressing);
2622}
2623
2624
2626(
2627 const UPtrList<polyMesh>& meshes,
2628 const UList<labelList>& patchMap,
2629
2630 const labelListList& localBoundaryFace,
2631 const labelListList& remoteFaceMesh,
2632 const labelListList& remoteBoundaryFace,
2633 const labelListList& remoteFaceStart,
2634
2635 const UList<labelList>& pointZoneMap,
2636 const UList<labelList>& faceZoneMap,
2637 const UList<labelList>& cellZoneMap,
2638
2639 polyTopoChange& meshMod,
2640 labelListList& cellProcAddressing,
2641 labelListList& faceProcAddressing,
2642 labelListList& pointProcAddressing
2643 //labelListList& boundaryProcAddressing
2644)
2645{
2646 cellProcAddressing.setSize(meshes.size());
2647 faceProcAddressing.setSize(meshes.size());
2648 pointProcAddressing.setSize(meshes.size());
2649 //boundaryProcAddressing.setSize(meshes.size());
2650 forAll(cellProcAddressing, meshi)
2651 {
2652 cellProcAddressing[meshi].clear();
2653 faceProcAddressing[meshi].clear();
2654 pointProcAddressing[meshi].clear();
2655 }
2656
2657 // Start off with points allocated in processor order.
2658 labelList offsets(meshes.size()+1);
2659 offsets[0] = 0;
2660 forAll(meshes, meshi)
2661 {
2662 label nPoints = 0;
2663 if (meshes.set(meshi))
2664 {
2665 const polyMesh& mesh = meshes[meshi];
2666 nPoints = mesh.nPoints();
2667 }
2668 pointProcAddressing[meshi] = identity(nPoints, offsets[meshi]);
2669 offsets[meshi+1] = offsets[meshi]+nPoints;
2670 }
2671 const globalIndex globalPoints(std::move(offsets));
2672
2673 labelListList uniquePoints(meshes.size());
2674 compactPoints
2675 (
2676 meshes,
2677
2678 localBoundaryFace,
2679 remoteFaceMesh,
2680 remoteBoundaryFace,
2681 remoteFaceStart,
2682
2684
2685 pointProcAddressing, // per proc, per point the compact,global point
2686 uniquePoints // per proc indices of local preserved points
2687 );
2688
2689
2690 // Add cells
2691 // ~~~~~~~~~
2692 // These are used by face adding later on
2693
2694 forAll(meshes, meshi)
2695 {
2696 if (meshes.set(meshi))
2697 {
2698 const polyMesh& mesh = meshes[meshi];
2699 const cellZoneMesh& cellZones = mesh.cellZones();
2700
2701 // Add cells in mesh order
2702 cellProcAddressing[meshi].setSize(mesh.nCells());
2703 DynamicList<label> zones;
2704 for (label celli = 0; celli < mesh.nCells(); celli++)
2705 {
2706 // Get current zones and renumber
2707 cellZones.whichZones(celli, zones);
2708 inplaceRenumber(cellZoneMap[meshi], zones);
2709 // Add cell from cell
2710 cellProcAddressing[meshi][celli] = meshMod.addCell
2711 (
2712 -1,
2713 -1,
2714 -1,
2715 celli,
2716 zones
2717 );
2718 }
2719 }
2720 }
2721
2722
2723 // Add points
2724 // ~~~~~~~~~~
2725 // These are used by face adding later on
2726
2727 forAll(meshes, meshi)
2728 {
2729 if (meshes.set(meshi))
2730 {
2731 const polyMesh& mesh = meshes[meshi];
2732 const pointField& points = mesh.points();
2733 const pointZoneMesh& pointZones = mesh.pointZones();
2734
2735 // Add points in mesh order
2736 const labelList& myUniquePoints = uniquePoints[meshi];
2737 DynamicList<label> zones;
2738 for (const label pointi : myUniquePoints)
2739 {
2740 // Get current zones and renumber
2741 pointZones.whichZones(pointi, zones);
2742 inplaceRenumber(pointZoneMap[meshi], zones);
2743 // Rewrite the addressing (should already be compact) just in
2744 // case the polyTopoChange does some special ordering
2745 pointProcAddressing[meshi][pointi] = meshMod.addPoint
2746 (
2747 points[pointi],
2748 pointi,
2749 zones,
2750 true
2751 );
2752 }
2753 }
2754 }
2755
2756
2757
2758 // Add faces
2759 // ~~~~~~~~~
2760
2761 forAll(meshes, meshi)
2762 {
2763 if (meshes.set(meshi))
2764 {
2765 const polyMesh& mesh = meshes[meshi];
2766 faceProcAddressing[meshi].setSize(mesh.nFaces());
2767 faceProcAddressing[meshi] = -1;
2768 //boundaryProcAddressing[meshi].setSize(mesh.boundaryMesh().size());
2769 //boundaryProcAddressing[meshi] = -1;
2770 }
2771 }
2772
2773 forAll(meshes, meshi)
2774 {
2775 if (meshes.set(meshi))
2776 {
2777 const polyMesh& mesh = meshes[meshi];
2779 const faceList& faces = mesh.faces();
2780 const labelList& faceOwner = mesh.faceOwner();
2781 const labelList& faceNeighbour = mesh.faceNeighbour();
2782 const faceZoneMesh& faceZones = mesh.faceZones();
2783
2784 DynamicList<label> zones;
2785 DynamicList<bool> flips;
2786
2787 // Add faces in mesh order
2788
2789 // 1. Internal faces
2790
2791 face newFace;
2792 for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
2793 {
2794 const face& f = faces[facei];
2795
2796 label newOwn = cellProcAddressing[meshi][faceOwner[facei]];
2797 label newNei = cellProcAddressing[meshi][faceNeighbour[facei]];
2798
2799 newFace.setSize(f.size());
2800 forAll(f, fp)
2801 {
2802 newFace[fp] = pointProcAddressing[meshi][f[fp]];
2803 }
2804
2805 // Get current zones and renumber
2806 faceZones.whichZones(facei, zones);
2807 flips.clear();
2808 forAll(zones, i)
2809 {
2810 const label zonei = zones[i];
2811 const label index = faceZones[zonei].localID(facei);
2812 flips.append(faceZones[zonei].flipMap()[index]);
2813 }
2814 inplaceRenumber(faceZoneMap[meshi], zones);
2815
2816 bool flipFaceFlux = false;
2817 if (newNei < newOwn)
2818 {
2819 std::swap(newOwn, newNei);
2820 newFace.flip();
2821 flipFaceFlux = !flipFaceFlux;
2822 for (bool& flip : flips)
2823 {
2824 flip = !flip;
2825 }
2826 }
2827
2828 const label newFacei = meshMod.addFace
2829 (
2830 newFace,
2831 newOwn,
2832 newNei,
2833 -1, // masterPointID
2834 -1, // masterEdgeID
2835 facei, // masterFaceID
2836 flipFaceFlux, // flipFaceFlux
2837 -1, // patchID
2838 zones, // zoneIDs
2839 flips // zoneFlips
2840 );
2841
2842 faceProcAddressing[meshi][facei] = newFacei;
2843 }
2844
2845 // 1b. Owner side of coupled faces (since owner side cells are
2846 // smallest)
2847
2848 const labelList& localBFaces = localBoundaryFace[meshi];
2849 const labelList& procNbrs = remoteFaceMesh[meshi];
2850 const labelList& procNbrBFaces = remoteBoundaryFace[meshi];
2851
2852 forAll(localBFaces, i)
2853 {
2854 const label bFacei = localBFaces[i];
2855 const label nbrMeshi = procNbrs[i];
2856 const label nbrBFacei = procNbrBFaces[i];
2857
2858 // Local mesh face
2859 const label facei = mesh.nInternalFaces()+bFacei;
2860 const face& f = mesh.faces()[facei];
2861 const label newOwn =
2862 cellProcAddressing[meshi][faceOwner[facei]];
2863
2864 faceZones.whichZones(facei, zones);
2865 flips.clear();
2866 forAll(zones, i)
2867 {
2868 const label zonei = zones[i];
2869 const label index = faceZones[zonei].localID(facei);
2870 flips.append(faceZones[zonei].flipMap()[index]);
2871 }
2872 inplaceRenumber(faceZoneMap[meshi], zones);
2873
2874
2875 // Neighbour mesh face
2876 const auto& nbrMesh = meshes[nbrMeshi];
2877 const label nbrFacei = nbrMesh.nInternalFaces()+nbrBFacei;
2878 const label nbrOwn = nbrMesh.faceOwner()[nbrFacei];
2879 const label newNei = cellProcAddressing[nbrMeshi][nbrOwn];
2880
2881 //Pout<< "** connection between face:" << facei
2882 // << " at:" << mesh.faceCentres()[facei]
2883 // << " and nbrMesh:" << nbrMeshi
2884 // << " nbrFacei:" << nbrMesh.faceCentres()[nbrFacei]
2885 // << endl;
2886
2887 if (newOwn < newNei)
2888 {
2889 newFace.setSize(f.size());
2890 forAll(f, fp)
2891 {
2892 newFace[fp] = pointProcAddressing[meshi][f[fp]];
2893 }
2894 const bool flipFaceFlux = false;
2895 const label newFacei = meshMod.addFace
2896 (
2897 newFace,
2898 newOwn,
2899 newNei, // neighbour
2900 -1, // masterPointID
2901 -1, // masterEdgeID
2902 facei, // masterFaceID
2903 flipFaceFlux, // flipFaceFlux
2904 -1, // patchID
2905 zones, // zoneIDs
2906 flips // zoneFlips
2907 );
2908
2909 faceProcAddressing[meshi][facei] = newFacei;
2910 faceProcAddressing[nbrMeshi][nbrFacei] = newFacei;
2911 }
2912 }
2913
2914
2915 // 2. Remaining patch faces
2916
2917 forAll(pbm, patchi)
2918 {
2919 const auto& pp = pbm[patchi];
2920
2921 if (patchi < patchMap[meshi].size())
2922 {
2923 const label newPatchi = patchMap[meshi][patchi];
2924
2925 //boundaryProcAddressing[meshi][patchi] = newPatchi;
2926
2927 forAll(pp, patchFacei)
2928 {
2929 const label facei = pp.start() + patchFacei;
2930 if (faceProcAddressing[meshi][facei] == -1)
2931 {
2932 const face& f = faces[facei];
2933
2934 const label newOwn =
2935 cellProcAddressing[meshi][faceOwner[facei]];
2936 newFace.setSize(f.size());
2937 forAll(f, fp)
2938 {
2939 newFace[fp] = pointProcAddressing[meshi][f[fp]];
2940 }
2941
2942 faceZones.whichZones(facei, zones);
2943 flips.clear();
2944 forAll(zones, i)
2945 {
2946 const label zonei = zones[i];
2947 const label index =
2948 faceZones[zonei].localID(facei);
2949 flips.append(faceZones[zonei].flipMap()[index]);
2950 }
2951 inplaceRenumber(faceZoneMap[meshi], zones);
2952
2953
2954 const label newFacei = meshMod.addFace
2955 (
2956 newFace,
2957 newOwn,
2958 -1, // neighbour
2959 -1, // masterPointID
2960 -1, // masterEdgeID
2961 facei, // masterFaceID
2962 false, // flipFaceFlux
2963 newPatchi, // patchID
2964 zones, // zoneID
2965 flips // zoneFlip
2966 );
2967
2968 faceProcAddressing[meshi][facei] = newFacei;
2969 }
2970 }
2971 }
2972 }
2973 }
2974 }
2975}
2976
2977
2978// ************************************************************************* //
label n
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
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
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
void append(const T &val)
Copy append an element to the end of this list.
Map from edge (expressed as its endpoints) to value. Hashing (and ==) on an edge is symmetric.
Definition edgeHashes.H:59
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition HashTableI.H:113
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition HashTableI.H:152
iterator find(const Key &key)
Find and return an iterator set at the hashed entry.
Definition HashTableI.H:86
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
label size() const noexcept
The number of elements in the list.
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 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
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie,...
Definition PtrList.H:171
void setSize(const label n)
Same as resize().
Definition PtrList.H:357
void append(autoPtr< T > &ptr)
Move append an element to the end of the list.
Definition PtrList.H:364
A list that is sorted upon construction or when explicitly requested with the sort() method.
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
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 found(const T &val, label pos=0) const
Same as contains().
Definition UList.H:983
label rcIndex(const label i) const noexcept
The reverse circular index. The previous index in the list which returns to the last at the beginning...
Definition UListI.H:106
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
label find(const T &val) const
Find index of the first occurrence of the value.
Definition UList.C:160
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition UPtrList.H:101
label size() const noexcept
The number of entries in the list.
Definition UPtrListI.H:106
label whichZones(const label objectIndex, DynamicList< label > &zones) const
Given a global object index, return (in argument) its zones.
Definition ZoneMesh.C:420
void clear()
Clear the zones.
Definition ZoneMesh.C:970
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition ZoneMesh.C:410
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition autoPtrI.H:37
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition autoPtr.H:178
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
A subset of mesh cells.
Definition cellZone.H:61
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
Definition edge.H:62
Container for information needed to couple to meshes. When constructed from two meshes and a geometri...
const primitiveFacePatch & cutFaces() const
Addressing engine for combined set of faces.
A subset of mesh faces organised as a primitive patch.
Definition faceZone.H:63
label whichFace(const label meshFaceID) const
The local index of the given mesh face, -1 if not in the zone.
Definition faceZone.H:394
const boolList & flipMap() const noexcept
Return face flip map.
Definition faceZone.H:389
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
void flip()
Flip the face in-place.
Definition face.C:492
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Definition globalIndex.H:77
Calculates points shared by more than two processor patches or cyclic patches.
Class containing mesh-to-mesh mapping information after a mesh addition where we add a mesh ('added m...
A subset of mesh points.
Definition pointZone.H:64
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
label nNonProcessor() const
The number of patches before the first processor patch.
labelList patchStarts() const
Return a list of patch start face indices.
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
labelList patchSizes() const
Return a list of patch sizes.
wordList names() const
Return a list of patch names.
static autoPtr< polyMesh > add(const IOobject &io, const polyMesh &mesh0, const polyMesh &mesh1, const faceCoupleInfo &coupleInfo, autoPtr< mapAddedPolyMesh > &mapPtr)
Add two polyMeshes. Returns new polyMesh and map construct.
static void mergePoints(const polyMesh &, const Map< label > &pointToMaster, polyTopoChange &meshMod)
Helper: Merge points.
static void patchFacePairs(const UPtrList< polyMesh > &meshes, const List< DynamicList< label > > &localPatch, const List< DynamicList< label > > &remoteMesh, const List< DynamicList< label > > &remotePatch, labelListList &localBoundaryFace, labelListList &remoteFaceMesh, labelListList &remoteBoundaryFace)
Helper: expand list of coupled patches into pairs of coupled faces.
static Map< label > findSharedPoints(const polyMesh &, const scalar mergeTol)
Find topologically and geometrically shared points.
static label procPatchPairs(const UPtrList< polyMesh > &meshes, List< DynamicList< label > > &localPatch, List< DynamicList< label > > &remoteMesh, List< DynamicList< label > > &remotePatch)
Helper: find pairs of processor patches. Return number of non-processor patches.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition polyMesh.H:609
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition polyMesh.H:671
virtual const faceList & faces() const
Return raw faces.
Definition polyMesh.C:1088
virtual const labelList & faceOwner() const
Return face owner.
Definition polyMesh.C:1101
void resetMotion() const
Reset motion.
Definition polyMesh.C:1282
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition polyMesh.H:679
void addZones(PtrList< pointZone > &&pz, PtrList< faceZone > &&fz, PtrList< cellZone > &&cz)
Add mesh zones.
Definition polyMesh.C:994
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition polyMesh.C:1107
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition polyMesh.H:663
virtual const pointField & points() const
Return raw points.
Definition polyMesh.C:1063
void resetPrimitives(autoPtr< pointField > &&points, autoPtr< faceList > &&faces, autoPtr< labelList > &&owner, autoPtr< labelList > &&neighbour, const labelUList &patchSizes, const labelUList &patchStarts, const bool validBoundary=true)
Reset mesh primitive data. Assumes all patch info correct.
Definition polyMesh.C:689
Class describing modification of a face.
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
Direct mesh changes based on v1.3 polyTopoChange syntax.
label addPoint(const point &pt, const label masterPointID, const label zoneID, const bool inCell)
Add point. Return new point label.
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
label addCell(const label masterPointID, const label masterEdgeID, const label masterFaceID, const label masterCellID, const label zoneID)
Add cell. Return new cell label.
void removePoint(const label pointi, const label mergePointi)
Remove/merge point.
label addFace(const face &f, const label own, const label nei, const label masterPointID, const label masterEdgeID, const label masterFaceID, const bool flipFaceFlux, const label patchID, const label zoneID, const bool zoneFlip)
Add face to cells. Return new face label.
label nInternalFaces() const noexcept
Number of internal faces.
label nPoints() const noexcept
Number of mesh points.
label nCells() const noexcept
Number of mesh cells.
label nFaces() const noexcept
Number of mesh faces.
Neighbour processor patch.
A class for handling words, derived from Foam::string.
Definition word.H:66
volScalarField & p
dynamicFvMesh & mesh
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
IOporosityModelList pZones(mesh)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const auto & io
auto & name
auto & names
const pointField & points
label nPoints
const cellShapeList & cells
Geometric merging of points. See below.
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition typeInfo.H:172
List< word > wordList
List of word.
Definition fileName.H:60
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values within a list.
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with pointZone content on a polyMesh.
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
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
UIndirectList< label > labelUIndList
UIndirectList of labels.
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values within a list.
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with faceZone content on a polyMesh.
List< face > faceList
List of faces.
Definition faceListFwd.H:41
constexpr label labelMax
Definition label.H:55
label mergePoints(const PointList &points, labelList &pointToUnique, labelList &uniquePoints, const scalar mergeTol=SMALL, const bool verbose=false)
Calculate merge mapping, preserving the original point order. All points closer/equal mergeTol are to...
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
A PrimitivePatch with List storage for the faces, const reference for the point field.
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
List< cell > cellList
List of cell.
Definition cellListFwd.H:41
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with cellZone content on a polyMesh.
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:26
List< List< bool > > boolListList
List of boolList.
Definition boolList.H:36
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
errorManip< error > abort(error &err)
Definition errorManip.H:139
List< bool > boolList
A List of bools.
Definition List.H:60
UIndirectList< bool > boolUIndList
UIndirectList of bools.
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
vectorField pointField
pointField is a vectorField.
labelListList invertOneToMany(const label len, const labelUList &map)
Invert one-to-many map. Unmapped elements will be size 0.
Definition ListOps.C:125
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
void stableSort(UList< T > &list)
Stable sort the list.
Definition UList.C:299
labelList f(nPoints)
volScalarField & e
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition stdFoam.H:315
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235