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