fvMeshDistribute.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-2018 OpenFOAM Foundation
9 Copyright (C) 2015-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "fvMeshDistribute.H"
30#include "fvMeshAdder.H"
31#include "fvMeshSubset.H"
32#include "faceCoupleInfo.H"
37#include "polyTopoChange.H"
38#include "removeCells.H"
39#include "polyModifyFace.H"
40#include "polyRemovePoint.H"
42#include "surfaceFields.H"
43#include "syncTools.H"
44#include "CompactListList.H"
45#include "fvMeshTools.H"
46#include "labelPairHashes.H"
47#include "ListOps.H"
48#include "globalIndex.H"
49#include "cyclicACMIPolyPatch.H"
50#include "mappedPatchBase.H"
51
52// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
53
54namespace Foam
55{
57
58 //- Less function class that can be used for sorting processor patches
60 {
61 const labelList& nbrProc_;
62 const labelList& referPatchID_;
63
64 public:
65
66 lessProcPatches(const labelList& nbrProc, const labelList& referPatchID)
67 :
68 nbrProc_(nbrProc),
69 referPatchID_(referPatchID)
70 {}
71
72 bool operator()(const label a, const label b)
73 {
74 if (nbrProc_[a] < nbrProc_[b])
75 {
76 return true;
77 }
78 else if (nbrProc_[a] > nbrProc_[b])
79 {
80 return false;
81 }
82 else
83 {
84 // Equal neighbour processor
85 return referPatchID_[a] < referPatchID_[b];
86 }
87 }
88 };
89}
90
91
92// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
93
94void Foam::fvMeshDistribute::inplaceRenumberWithFlip
95(
96 const labelUList& oldToNew,
97 const bool oldToNewHasFlip,
98 const bool lstHasFlip,
99 labelUList& lst
100)
101{
102 if (!lstHasFlip && !oldToNewHasFlip)
103 {
104 Foam::inplaceRenumber(oldToNew, lst);
105 }
106 else
107 {
108 // Either input data or map encodes sign so result encodes sign
109
110 forAll(lst, elemI)
111 {
112 // Extract old value and sign
113 label val = lst[elemI];
114 label sign = 1;
115 if (lstHasFlip)
116 {
117 if (val > 0)
118 {
119 val = val-1;
120 }
121 else if (val < 0)
122 {
123 val = -val-1;
124 sign = -1;
125 }
126 else
127 {
129 << "Problem : zero value " << val
130 << " at index " << elemI << " out of " << lst.size()
131 << " list with flip bit" << exit(FatalError);
132 }
133 }
134
135
136 // Lookup new value and possibly change sign
137 label newVal = oldToNew[val];
138
139 if (oldToNewHasFlip)
140 {
141 if (newVal > 0)
142 {
143 newVal = newVal-1;
144 }
145 else if (newVal < 0)
146 {
147 newVal = -newVal-1;
148 sign = -sign;
149 }
150 else
151 {
153 << "Problem : zero value " << newVal
154 << " at index " << elemI << " out of "
155 << oldToNew.size()
156 << " list with flip bit" << exit(FatalError);
157 }
158 }
159
160
161 // Encode new value and sign
162 lst[elemI] = sign*(newVal+1);
163 }
164 }
165}
166
167
168Foam::labelList Foam::fvMeshDistribute::select
169(
170 const bool selectEqual,
171 const labelList& values,
172 const label value
173)
174{
175 label n = 0;
176
177 forAll(values, i)
178 {
179 if (selectEqual == (values[i] == value))
180 {
181 n++;
182 }
183 }
184
185 labelList indices(n);
186 n = 0;
187
188 forAll(values, i)
189 {
190 if (selectEqual == (values[i] == value))
191 {
192 indices[n++] = i;
193 }
194 }
195 return indices;
196}
197
198
199Foam::wordList Foam::fvMeshDistribute::mergeWordList(const wordList& procNames)
200{
201 List<wordList> allNames(Pstream::nProcs());
202 allNames[Pstream::myProcNo()] = procNames;
203 Pstream::gatherList(allNames);
204
205 // Assume there are few zone names to merge. Use HashSet otherwise (but
206 // maintain ordering)
207 DynamicList<word> mergedNames;
208 if (Pstream::master())
209 {
210 mergedNames = procNames;
211 for (const wordList& names : allNames)
212 {
213 for (const word& name : names)
214 {
215 mergedNames.appendUniq(name);
216 }
217 }
218 }
219 Pstream::scatter(mergedNames);
220
221 return mergedNames;
222}
223
224
226{
227 Pout<< "Primitives:" << nl
228 << " points :" << mesh.nPoints() << nl
229 << " bb :" << boundBox(mesh.points(), false) << nl
230 << " internalFaces:" << mesh.nInternalFaces() << nl
231 << " faces :" << mesh.nFaces() << nl
232 << " cells :" << mesh.nCells() << nl;
233
235
236 Pout<< "Patches:" << endl;
237 forAll(patches, patchi)
238 {
239 const polyPatch& pp = patches[patchi].patch();
240
241 Pout<< " " << patchi << " name:" << pp.name()
242 << " size:" << pp.size()
243 << " start:" << pp.start()
244 << " type:" << pp.type()
245 << endl;
246 }
247
248 if (mesh.pointZones().size())
249 {
250 Pout<< "PointZones:" << endl;
251 forAll(mesh.pointZones(), zoneI)
252 {
253 const pointZone& pz = mesh.pointZones()[zoneI];
254 Pout<< " " << zoneI << " name:" << pz.name()
255 << " size:" << pz.size()
256 << endl;
257 }
258 }
259 if (mesh.faceZones().size())
260 {
261 Pout<< "FaceZones:" << endl;
262 forAll(mesh.faceZones(), zoneI)
263 {
264 const faceZone& fz = mesh.faceZones()[zoneI];
265 Pout<< " " << zoneI << " name:" << fz.name()
266 << " size:" << fz.size()
267 << endl;
268 }
269 }
270 if (mesh.cellZones().size())
271 {
272 Pout<< "CellZones:" << endl;
273 forAll(mesh.cellZones(), zoneI)
274 {
275 const cellZone& cz = mesh.cellZones()[zoneI];
276 Pout<< " " << zoneI << " name:" << cz.name()
277 << " size:" << cz.size()
278 << endl;
279 }
280 }
281}
282
283
285(
286 const primitiveMesh& mesh,
287 const labelList& sourceFace,
288 const labelList& sourceProc,
289 const labelList& sourcePatch,
290 const labelList& sourceNewNbrProc
291)
292{
293 Pout<< nl
294 << "Current coupling info:"
295 << endl;
296
297 forAll(sourceFace, bFacei)
298 {
299 label meshFacei = mesh.nInternalFaces() + bFacei;
300
301 Pout<< " meshFace:" << meshFacei
302 << " fc:" << mesh.faceCentres()[meshFacei]
303 << " connects to proc:" << sourceProc[bFacei]
304 << "/face:" << sourceFace[bFacei]
305 << " which will move to proc:" << sourceNewNbrProc[bFacei]
306 << endl;
307 }
308}
309
310
311Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
312{
313 // Finds (non-empty) patch that exposed internal and proc faces can be
314 // put into.
315 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
316
317
318 // Mark 'special' patches : -coupled, -duplicate faces. These probably
319 // should not be used to (temporarily) store processor faces ...
320
321 bitSet isCoupledPatch(patches.size());
322 forAll(patches, patchi)
323 {
324 const polyPatch& pp = patches[patchi];
325 const auto* cpp = isA<cyclicACMIPolyPatch>(pp);
326
327 if (cpp)
328 {
329 isCoupledPatch.set(patchi);
330 const label dupPatchID = cpp->nonOverlapPatchID();
331 if (dupPatchID != -1)
332 {
333 isCoupledPatch.set(dupPatchID);
334 }
335 }
336 else if (pp.coupled())
337 {
338 isCoupledPatch.set(patchi);
339 }
340 }
341
342 label nonEmptyPatchi = -1;
343
344 forAllReverse(patches, patchi)
345 {
346 const polyPatch& pp = patches[patchi];
347
348 if
349 (
350 !isA<emptyPolyPatch>(pp)
351 && !isCoupledPatch(patchi)
352 && !isA<mappedPatchBase>(pp)
353 )
354 {
355 nonEmptyPatchi = patchi;
356 break;
357 }
358 }
359
360 if (nonEmptyPatchi == -1)
361 {
363 << "Cannot find a patch which is neither of type empty nor"
364 << " coupled in patches " << patches.names() << endl
365 << "There has to be at least one such patch for"
366 << " distribution to work" << abort(FatalError);
367 }
368
369 if (debug)
370 {
371 Pout<< "findNonEmptyPatch : using patch " << nonEmptyPatchi
372 << " name:" << patches[nonEmptyPatchi].name()
373 << " type:" << patches[nonEmptyPatchi].type()
374 << " to put exposed faces into." << endl;
375 }
376
377
378 // Do additional test for processor patches intermingled with non-proc
379 // patches.
380 label procPatchi = -1;
381
382 forAll(patches, patchi)
383 {
384 if (isA<processorPolyPatch>(patches[patchi]))
385 {
386 procPatchi = patchi;
387 }
388 else if (procPatchi != -1)
389 {
391 << "Processor patches should be at end of patch list."
392 << endl
393 << "Have processor patch " << procPatchi
394 << " followed by non-processor patch " << patchi
395 << " in patches " << patches.names()
396 << abort(FatalError);
397 }
398 }
399
400 return nonEmptyPatchi;
401}
402
403
405(
406 const fvMesh& mesh
407)
408{
409 const vector testNormal = normalised(vector::one);
410
412 (
414 (
416 (
417 "myFlux",
418 mesh.time().timeName(),
419 mesh,
422 ),
423 mesh,
425 )
426 );
427 surfaceScalarField& fld = tfld.ref();
428
430
431 forAll(fld, facei)
432 {
433 fld[facei] = (n[facei] & testNormal);
434 }
435
436 surfaceScalarField::Boundary& fluxBf = fld.boundaryFieldRef();
437 const surfaceVectorField::Boundary& nBf = n.boundaryField();
438
439 forAll(fluxBf, patchi)
440 {
441 fvsPatchScalarField& fvp = fluxBf[patchi];
442
443 scalarField newPfld(fvp.size());
444 forAll(newPfld, i)
445 {
446 newPfld[i] = (nBf[patchi][i] & testNormal);
447 }
448 fvp == newPfld;
449 }
450
451 return tfld;
452}
453
454
456{
457 const fvMesh& mesh = fld.mesh();
458
459 const vector testNormal = normalised(vector::one);
460
462
463 forAll(fld, facei)
464 {
465 scalar cos = (n[facei] & testNormal);
466
467 if (mag(cos - fld[facei]) > 1e-6)
468 {
469 //FatalErrorInFunction
471 << "On internal face " << facei << " at "
472 << mesh.faceCentres()[facei]
473 << " the field value is " << fld[facei]
474 << " whereas cos angle of " << testNormal
475 << " with mesh normal " << n[facei]
476 << " is " << cos
477 //<< exit(FatalError);
478 << endl;
479 }
480 }
481 forAll(fld.boundaryField(), patchi)
482 {
483 const fvsPatchScalarField& fvp = fld.boundaryField()[patchi];
484 const fvsPatchVectorField& np = n.boundaryField()[patchi];
485
486 forAll(fvp, i)
487 {
488 scalar cos = (np[i] & testNormal);
489
490 if (mag(cos - fvp[i]) > 1e-6)
491 {
492 label facei = fvp.patch().start()+i;
493 //FatalErrorInFunction
495 << "On face " << facei
496 << " on patch " << fvp.patch().name()
497 << " at " << mesh.faceCentres()[facei]
498 << " the field value is " << fvp[i]
499 << " whereas cos angle of " << testNormal
500 << " with mesh normal " << np[i]
501 << " is " << cos
502 //<< exit(FatalError);
503 << endl;
504 }
505 }
506 }
507}
508
509
510Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::deleteProcPatches
511(
512 const label destinationPatch
513)
514{
515 // Delete all processor patches. Move any processor faces into the last
516 // non-processor patch.
517
518 // New patchID per boundary faces to be repatched. Is -1 (no change)
519 // or new patchID
520 labelList newPatchID(mesh_.nBoundaryFaces(), -1);
521
522 for (const polyPatch& pp : mesh_.boundaryMesh())
523 {
524 if (isA<processorPolyPatch>(pp))
525 {
526 if (debug)
527 {
528 Pout<< "Moving all faces of patch " << pp.name()
529 << " into patch " << destinationPatch
530 << endl;
531 }
532
533 SubList<label>
534 (
535 newPatchID,
536 pp.size(),
537 pp.offset()
538 ) = destinationPatch;
539 }
540 }
541
542 // Note: order of boundary faces been kept the same since the
543 // destinationPatch is at the end and we have visited the patches in
544 // incremental order.
545 labelListList dummyFaceMaps;
546 autoPtr<mapPolyMesh> map = repatch(newPatchID, dummyFaceMaps);
547
548
549 // Delete (now empty) processor patches.
550 {
551 labelList oldToNew(identity(mesh_.boundaryMesh().size()));
552 label newi = 0;
553 // Non processor patches first
554 forAll(mesh_.boundaryMesh(), patchi)
555 {
556 if (!isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
557 {
558 oldToNew[patchi] = newi++;
559 }
560 }
561 label nNonProcPatches = newi;
562
563 // Processor patches as last
564 forAll(mesh_.boundaryMesh(), patchi)
565 {
566 if (isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
567 {
568 oldToNew[patchi] = newi++;
569 }
570 }
571 fvMeshTools::reorderPatches(mesh_, oldToNew, nNonProcPatches, false);
572 }
573
574 return map;
575}
576
577
579(
580 const labelList& newPatchID, // per boundary face -1 or new patchID
581 labelListList& constructFaceMap
582)
583{
584 polyTopoChange meshMod(mesh_);
585
586 forAll(newPatchID, bFacei)
587 {
588 if (newPatchID[bFacei] != -1)
589 {
590 label facei = mesh_.nInternalFaces() + bFacei;
591
592 label zoneID = mesh_.faceZones().whichZone(facei);
593 bool zoneFlip = false;
594
595 if (zoneID >= 0)
596 {
597 const faceZone& fZone = mesh_.faceZones()[zoneID];
598 zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
599 }
600
601 meshMod.setAction
602 (
603 polyModifyFace
604 (
605 mesh_.faces()[facei], // modified face
606 facei, // label of face
607 mesh_.faceOwner()[facei], // owner
608 -1, // neighbour
609 false, // face flip
610 newPatchID[bFacei], // patch for face
611 false, // remove from zone
612 zoneID, // zone for face
613 zoneFlip // face flip in zone
614 )
615 );
616 }
617 }
618
619
620 // Do mapping of fields from one patchField to the other ourselves since
621 // is currently not supported by updateMesh.
622
623 // Store boundary fields (we only do this for surfaceFields)
624 PtrList<FieldField<fvsPatchField, scalar>> sFlds;
625 saveBoundaryFields<scalar, surfaceMesh>(sFlds);
626 PtrList<FieldField<fvsPatchField, vector>> vFlds;
627 saveBoundaryFields<vector, surfaceMesh>(vFlds);
628 PtrList<FieldField<fvsPatchField, sphericalTensor>> sptFlds;
629 saveBoundaryFields<sphericalTensor, surfaceMesh>(sptFlds);
630 PtrList<FieldField<fvsPatchField, symmTensor>> sytFlds;
631 saveBoundaryFields<symmTensor, surfaceMesh>(sytFlds);
632 PtrList<FieldField<fvsPatchField, tensor>> tFlds;
633 saveBoundaryFields<tensor, surfaceMesh>(tFlds);
634
635 // Change the mesh (no inflation). Note: parallel comms allowed.
636 //
637 // NOTE: there is one very particular problem with this ordering.
638 // We first create the processor patches and use these to merge out
639 // shared points (see mergeSharedPoints below). So temporarily points
640 // and edges do not match!
641
642 // TBD: temporarily unset mesh moving to avoid problems in meshflux
643 // mapping. To be investigated.
644 const bool oldMoving = mesh_.moving(false);
645 autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
646 mesh_.moving(oldMoving);
647 mapPolyMesh& map = *mapPtr;
648
649
650 // Update fields. No inflation, parallel sync.
651 mesh_.updateMesh(map);
652
653 // Map patch fields using stored boundary fields. Note: assumes order
654 // of fields has not changed in object registry!
655 mapBoundaryFields<scalar, surfaceMesh>(map, sFlds);
656 mapBoundaryFields<vector, surfaceMesh>(map, vFlds);
657 mapBoundaryFields<sphericalTensor, surfaceMesh>(map, sptFlds);
658 mapBoundaryFields<symmTensor, surfaceMesh>(map, sytFlds);
659 mapBoundaryFields<tensor, surfaceMesh>(map, tFlds);
660
661
662 // Move mesh (since morphing does not do this)
663 if (map.hasMotionPoints())
664 {
665 mesh_.movePoints(map.preMotionPoints());
666 }
667
668 // Adapt constructMaps.
669
670 if (debug)
671 {
672 label index = map.reverseFaceMap().find(-1);
673
674 if (index != -1)
675 {
677 << "reverseFaceMap contains -1 at index:"
678 << index << endl
679 << "This means that the repatch operation was not just"
680 << " a shuffle?" << abort(FatalError);
681 }
682 }
683
684 forAll(constructFaceMap, proci)
685 {
686 inplaceRenumberWithFlip
687 (
688 map.reverseFaceMap(),
689 false,
690 true,
691 constructFaceMap[proci]
692 );
693 }
694
695 return mapPtr;
696}
697
698
699// Detect shared points. Need processor patches to be present.
700// Background: when adding bits of mesh one can get points which
701// share the same position but are only detectable to be topologically
702// the same point when doing parallel analysis. This routine will
703// merge those points.
704Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
705(
706 const labelList& pointToGlobalMaster,
707 labelListList& constructPointMap
708)
709{
710 // Find out which sets of points get merged and create a map from
711 // mesh point to unique point.
712
713 label nShared = 0;
714 forAll(pointToGlobalMaster, pointi)
715 {
716 if (pointToGlobalMaster[pointi] != -1)
717 {
718 nShared++;
719 }
720 }
721
722 if (debug)
723 {
724 Pout<< "mergeSharedPoints : found " << nShared
725 << " points on processor boundaries" << nl << endl;
726 }
727
728 Map<label> globalMasterToLocalMaster(2*nShared);
729 Map<label> pointToMaster(2*nShared);
730 label nMatch = 0;
731
732 forAll(pointToGlobalMaster, pointi)
733 {
734 label globali = pointToGlobalMaster[pointi];
735 if (globali != -1)
736 {
737 const auto iter = globalMasterToLocalMaster.cfind(globali);
738
739 if (iter.found())
740 {
741 // Matched to existing master
742 pointToMaster.insert(pointi, *iter);
743 nMatch++;
744 }
745 else
746 {
747 // Found first point. Designate as master
748 globalMasterToLocalMaster.insert(globali, pointi);
749 pointToMaster.insert(pointi, pointi);
750 }
751 }
752 }
753
754 reduce(nMatch, sumOp<label>());
755
756 if (debug)
757 {
758 Pout<< "mergeSharedPoints : found "
759 << nMatch << " mergeable points" << nl << endl;
760 }
761
762
763 if (nMatch == 0)
764 {
765 return nullptr;
766 }
767
768
769 polyTopoChange meshMod(mesh_);
770
771 fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
772
773 // Change the mesh (no inflation). Note: parallel comms allowed.
774
775 // TBD: temporarily unset mesh moving to avoid problems in meshflux
776 // mapping. To be investigated.
777 const bool oldMoving = mesh_.moving(false);
778 autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
779 mesh_.moving(oldMoving);
780 mapPolyMesh& map = *mapPtr;
781
782 // Update fields. No inflation, parallel sync.
783 mesh_.updateMesh(map);
784
785 // Adapt constructMaps for merged points.
786 forAll(constructPointMap, proci)
787 {
788 labelList& constructMap = constructPointMap[proci];
789
790 forAll(constructMap, i)
791 {
792 label oldPointi = constructMap[i];
793
794 label newPointi = map.reversePointMap()[oldPointi];
795
796 if (newPointi < -1)
797 {
798 constructMap[i] = -newPointi-2;
799 }
800 else if (newPointi >= 0)
801 {
802 constructMap[i] = newPointi;
803 }
804 else
805 {
807 << "Problem. oldPointi:" << oldPointi
808 << " newPointi:" << newPointi << abort(FatalError);
809 }
810 }
811 }
812
813 return mapPtr;
814}
815
816
817void Foam::fvMeshDistribute::getCouplingData
818(
819 const labelList& distribution,
820 labelList& sourceFace,
821 labelList& sourceProc,
822 labelList& sourcePatch,
823 labelList& sourceNewNbrProc,
824 labelList& sourcePointMaster
825) const
826{
827 // Construct the coupling information for all (boundary) faces and
828 // points
829
830 const label nBnd = mesh_.nBoundaryFaces();
831 sourceFace.setSize(nBnd);
832 sourceProc.setSize(nBnd);
833 sourcePatch.setSize(nBnd);
834 sourceNewNbrProc.setSize(nBnd);
835
836 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
837
838 // Get neighbouring meshFace labels and new processor of coupled boundaries.
839 labelList nbrFaces(nBnd, -1);
840 labelList nbrNewNbrProc(nBnd, -1);
841
842 forAll(patches, patchi)
843 {
844 const polyPatch& pp = patches[patchi];
845
846 if (pp.coupled())
847 {
848 label offset = pp.start() - mesh_.nInternalFaces();
849
850 // Mesh labels of faces on this side
851 forAll(pp, i)
852 {
853 label bndI = offset + i;
854 nbrFaces[bndI] = pp.start()+i;
855 }
856
857 // Which processor they will end up on
858 SubList<label>(nbrNewNbrProc, pp.size(), offset) =
859 labelUIndList(distribution, pp.faceCells())();
860 }
861 }
862
863
864 // Exchange the boundary data
865 syncTools::swapBoundaryFaceList(mesh_, nbrFaces);
866 syncTools::swapBoundaryFaceList(mesh_, nbrNewNbrProc);
867
868
869 forAll(patches, patchi)
870 {
871 const polyPatch& pp = patches[patchi];
872 label offset = pp.start() - mesh_.nInternalFaces();
873
874 if (isA<processorPolyPatch>(pp))
875 {
876 const processorPolyPatch& procPatch =
877 refCast<const processorPolyPatch>(pp);
878
879 // Check which of the two faces we store.
880
881 if (procPatch.owner())
882 {
883 // Use my local face labels
884 forAll(pp, i)
885 {
886 label bndI = offset + i;
887 sourceFace[bndI] = pp.start()+i;
888 sourceProc[bndI] = Pstream::myProcNo();
889 sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
890 }
891 }
892 else
893 {
894 // Use my neighbours face labels
895 forAll(pp, i)
896 {
897 label bndI = offset + i;
898 sourceFace[bndI] = nbrFaces[bndI];
899 sourceProc[bndI] = procPatch.neighbProcNo();
900 sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
901 }
902 }
903
904
905 label patchi = -1;
906 if (isA<processorCyclicPolyPatch>(pp))
907 {
908 patchi = refCast<const processorCyclicPolyPatch>
909 (
910 pp
911 ).referPatchID();
912 }
913
914 forAll(pp, i)
915 {
916 label bndI = offset + i;
917 sourcePatch[bndI] = patchi;
918 }
919 }
920 else if (isA<cyclicPolyPatch>(pp))
921 {
922 const cyclicPolyPatch& cpp = refCast<const cyclicPolyPatch>(pp);
923
924 if (cpp.owner())
925 {
926 forAll(pp, i)
927 {
928 label bndI = offset + i;
929 sourceFace[bndI] = pp.start()+i;
930 sourceProc[bndI] = Pstream::myProcNo();
931 sourcePatch[bndI] = patchi;
932 sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
933 }
934 }
935 else
936 {
937 forAll(pp, i)
938 {
939 label bndI = offset + i;
940 sourceFace[bndI] = nbrFaces[bndI];
941 sourceProc[bndI] = Pstream::myProcNo();
942 sourcePatch[bndI] = patchi;
943 sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
944 }
945 }
946 }
947 else
948 {
949 // Normal (physical) boundary
950 forAll(pp, i)
951 {
952 label bndI = offset + i;
953 sourceFace[bndI] = -1;
954 sourceProc[bndI] = -1;
955 sourcePatch[bndI] = patchi;
956 sourceNewNbrProc[bndI] = -1;
957 }
958 }
959 }
960
961
962 // Collect coupled (collocated) points
963 sourcePointMaster.setSize(mesh_.nPoints());
964 sourcePointMaster = -1;
965 {
966 // Assign global master point
967 const globalIndex globalPoints(mesh_.nPoints());
968
969 const globalMeshData& gmd = mesh_.globalData();
970 const indirectPrimitivePatch& cpp = gmd.coupledPatch();
971 const labelList& meshPoints = cpp.meshPoints();
972 const mapDistribute& slavesMap = gmd.globalCoPointSlavesMap();
973 const labelListList& slaves = gmd.globalCoPointSlaves();
974
975 labelList elems(slavesMap.constructSize(), -1);
976 forAll(meshPoints, pointi)
977 {
978 const labelList& slots = slaves[pointi];
979
980 if (slots.size())
981 {
982 // pointi is a master. Assign a unique label.
983
984 label globalPointi = globalPoints.toGlobal(meshPoints[pointi]);
985 elems[pointi] = globalPointi;
986 forAll(slots, i)
987 {
988 label sloti = slots[i];
989 if (sloti >= meshPoints.size())
990 {
991 // Filter out local collocated points. We don't want
992 // to merge these
993 elems[slots[i]] = globalPointi;
994 }
995 }
996 }
997 }
998
999 // Push slave-slot data back to slaves
1000 slavesMap.reverseDistribute(elems.size(), elems, false);
1001
1002 // Extract back onto mesh
1003 forAll(meshPoints, pointi)
1004 {
1005 sourcePointMaster[meshPoints[pointi]] = elems[pointi];
1006 }
1007 }
1008}
1009
1010
1011// Subset the neighbourCell/neighbourProc fields
1012void Foam::fvMeshDistribute::subsetCouplingData
1013(
1014 const fvMesh& mesh,
1015 const labelList& pointMap,
1016 const labelList& faceMap,
1017 const labelList& cellMap,
1018
1019 const labelList& oldDistribution,
1020 const labelList& oldFaceOwner,
1021 const labelList& oldFaceNeighbour,
1022 const label oldInternalFaces,
1023
1024 const labelList& sourceFace,
1025 const labelList& sourceProc,
1026 const labelList& sourcePatch,
1027 const labelList& sourceNewNbrProc,
1028 const labelList& sourcePointMaster,
1029
1030 labelList& subFace,
1031 labelList& subProc,
1032 labelList& subPatch,
1033 labelList& subNewNbrProc,
1034 labelList& subPointMaster
1035)
1036{
1037 subFace.setSize(mesh.nBoundaryFaces());
1038 subProc.setSize(mesh.nBoundaryFaces());
1039 subPatch.setSize(mesh.nBoundaryFaces());
1040 subNewNbrProc.setSize(mesh.nBoundaryFaces());
1041
1042 forAll(subFace, newBFacei)
1043 {
1044 label newFacei = newBFacei + mesh.nInternalFaces();
1045
1046 label oldFacei = faceMap[newFacei];
1047
1048 // Was oldFacei internal face? If so which side did we get.
1049 if (oldFacei < oldInternalFaces)
1050 {
1051 subFace[newBFacei] = oldFacei;
1052 subProc[newBFacei] = Pstream::myProcNo();
1053 subPatch[newBFacei] = -1;
1054
1055 label oldOwn = oldFaceOwner[oldFacei];
1056 label oldNei = oldFaceNeighbour[oldFacei];
1057
1058 if (oldOwn == cellMap[mesh.faceOwner()[newFacei]])
1059 {
1060 // We kept the owner side. Where does the neighbour move to?
1061 subNewNbrProc[newBFacei] = oldDistribution[oldNei];
1062 }
1063 else
1064 {
1065 // We kept the neighbour side.
1066 subNewNbrProc[newBFacei] = oldDistribution[oldOwn];
1067 }
1068 }
1069 else
1070 {
1071 // Was boundary face. Take over boundary information
1072 label oldBFacei = oldFacei - oldInternalFaces;
1073
1074 subFace[newBFacei] = sourceFace[oldBFacei];
1075 subProc[newBFacei] = sourceProc[oldBFacei];
1076 subPatch[newBFacei] = sourcePatch[oldBFacei];
1077 subNewNbrProc[newBFacei] = sourceNewNbrProc[oldBFacei];
1078 }
1079 }
1080
1081
1082 subPointMaster = UIndirectList<label>(sourcePointMaster, pointMap);
1083}
1084
1085
1086// Find cells on mesh whose faceID/procID match the neighbour cell/proc of
1087// domainMesh. Store the matching face.
1088void Foam::fvMeshDistribute::findCouples
1089(
1090 const primitiveMesh& mesh,
1091 const labelList& sourceFace,
1092 const labelList& sourceProc,
1093 const labelList& sourcePatch,
1094
1095 const label domain,
1096 const primitiveMesh& domainMesh,
1097 const labelList& domainFace,
1098 const labelList& domainProc,
1099 const labelList& domainPatch,
1100
1101 labelList& masterCoupledFaces,
1102 labelList& slaveCoupledFaces
1103)
1104{
1105 // Store domain neighbour as map so we can easily look for pair
1106 // with same face+proc.
1107 labelPairLookup map(domainFace.size());
1108
1109 forAll(domainProc, bFacei)
1110 {
1111 if (domainProc[bFacei] != -1 && domainPatch[bFacei] == -1)
1112 {
1113 map.insert
1114 (
1115 labelPair(domainFace[bFacei], domainProc[bFacei]),
1116 bFacei
1117 );
1118 }
1119 }
1120
1121
1122 // Try to match mesh data.
1123
1124 masterCoupledFaces.setSize(domainFace.size());
1125 slaveCoupledFaces.setSize(domainFace.size());
1126 label coupledI = 0;
1127
1128 forAll(sourceFace, bFacei)
1129 {
1130 if (sourceProc[bFacei] != -1 && sourcePatch[bFacei] == -1)
1131 {
1132 labelPair myData(sourceFace[bFacei], sourceProc[bFacei]);
1133
1134 const auto iter = map.cfind(myData);
1135
1136 if (iter.found())
1137 {
1138 label nbrBFacei = *iter;
1139
1140 masterCoupledFaces[coupledI] = mesh.nInternalFaces() + bFacei;
1141 slaveCoupledFaces[coupledI] =
1142 domainMesh.nInternalFaces()
1143 + nbrBFacei;
1144
1145 coupledI++;
1146 }
1147 }
1148 }
1149
1150 masterCoupledFaces.setSize(coupledI);
1151 slaveCoupledFaces.setSize(coupledI);
1152
1153 if (debug)
1154 {
1155 Pout<< "findCouples : found " << coupledI
1156 << " faces that will be stitched" << nl << endl;
1157 }
1158}
1159
1160
1161void Foam::fvMeshDistribute::findCouples
1162(
1163 const UPtrList<polyMesh>& meshes,
1164 const PtrList<labelList>& domainSourceFaces,
1165 const PtrList<labelList>& domainSourceProcs,
1166 const PtrList<labelList>& domainSourcePatchs,
1167
1168 labelListList& localBoundaryFace,
1169 labelListList& remoteFaceProc,
1170 labelListList& remoteBoundaryFace
1171)
1172{
1173 // Collect all matching processor face pairs. These are all the
1174 // faces for which we have both sides
1175
1176 // Pass 0: count number of inter-processor faces
1177 labelList nProcFaces(meshes.size(), 0);
1178 forAll(meshes, meshi)
1179 {
1180 if (meshes.set(meshi))
1181 {
1182 const labelList& domainProc = domainSourceProcs[meshi];
1183 const labelList& domainPatch = domainSourcePatchs[meshi];
1184
1185 forAll(domainProc, bFacei)
1186 {
1187 if (domainProc[bFacei] != -1 && domainPatch[bFacei] == -1)
1188 {
1189 nProcFaces[meshi]++;
1190 }
1191 }
1192 }
1193 }
1194
1195 if (debug)
1196 {
1197 Pout<< "fvMeshDistribute::findCouples : nProcFaces:"
1198 << flatOutput(nProcFaces) << endl;
1199 }
1200
1201
1202 // Size
1203 List<DynamicList<label>> dynLocalFace(Pstream::nProcs());
1204 List<DynamicList<label>> dynRemoteProc(Pstream::nProcs());
1205 List<DynamicList<label>> dynRemoteFace(Pstream::nProcs());
1206
1207 forAll(meshes, meshi)
1208 {
1209 if (meshes.set(meshi))
1210 {
1211 dynLocalFace[meshi].setCapacity(nProcFaces[meshi]);
1212 dynRemoteProc[meshi].setCapacity(nProcFaces[meshi]);
1213 dynRemoteFace[meshi].setCapacity(nProcFaces[meshi]);
1214 }
1215 }
1216
1217
1218 // Insert all into big map. Find matches
1219 LabelPairMap<labelPair> map(2*sum(nProcFaces));
1220
1221 nProcFaces = 0;
1222
1223 forAll(meshes, meshi)
1224 {
1225 if (meshes.set(meshi))
1226 {
1227 const labelList& domainFace = domainSourceFaces[meshi];
1228 const labelList& domainProc = domainSourceProcs[meshi];
1229 const labelList& domainPatch = domainSourcePatchs[meshi];
1230
1231 forAll(domainProc, bFacei)
1232 {
1233 if (domainProc[bFacei] != -1 && domainPatch[bFacei] == -1)
1234 {
1235 const labelPair key
1236 (
1237 domainProc[bFacei],
1238 domainFace[bFacei]
1239 );
1240 auto fnd = map.find(key);
1241
1242 if (!fnd.found())
1243 {
1244 // Insert
1245 map.emplace(key, meshi, bFacei);
1246 }
1247 else
1248 {
1249 // Second occurence. Found match.
1250 const label matchProci = fnd().first();
1251 const label matchFacei = fnd().second();
1252
1253 dynLocalFace[meshi].append(bFacei);
1254 dynRemoteProc[meshi].append(matchProci);
1255 dynRemoteFace[meshi].append(matchFacei);
1256 nProcFaces[meshi]++;
1257
1258 dynLocalFace[matchProci].append(matchFacei);
1259 dynRemoteProc[matchProci].append(meshi);
1260 dynRemoteFace[matchProci].append(bFacei);
1261 nProcFaces[matchProci]++;
1262 }
1263 }
1264 }
1265 }
1266 }
1267
1268 if (debug)
1269 {
1270 Pout<< "fvMeshDistribute::findCouples : stored procFaces:"
1271 << map.size() << endl;
1272 }
1273
1274 localBoundaryFace.setSize(Pstream::nProcs());
1275 remoteFaceProc.setSize(Pstream::nProcs());
1276 remoteBoundaryFace.setSize(Pstream::nProcs());
1277 forAll(meshes, meshi)
1278 {
1279 if (meshes.set(meshi))
1280 {
1281 localBoundaryFace[meshi] = std::move(dynLocalFace[meshi]);
1282 remoteFaceProc[meshi] = std::move(dynRemoteProc[meshi]);
1283 remoteBoundaryFace[meshi] = std::move(dynRemoteFace[meshi]);
1284 }
1285 }
1286
1287
1288 if (debug)
1289 {
1290 Pout<< "fvMeshDistribute::findCouples : found matches:"
1291 << flatOutput(nProcFaces) << endl;
1292 }
1293}
1294
1295
1296// Map data on boundary faces to new mesh (resulting from adding two meshes)
1297Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
1298(
1299 const primitiveMesh& mesh, // mesh after adding
1300 const mapAddedPolyMesh& map,
1301 const labelList& boundaryData0, // on mesh before adding
1302 const label nInternalFaces1,
1303 const labelList& boundaryData1 // on added mesh
1304)
1305{
1306 labelList newBoundaryData(mesh.nBoundaryFaces());
1307
1308 forAll(boundaryData0, oldBFacei)
1309 {
1310 label newFacei = map.oldFaceMap()[oldBFacei + map.nOldInternalFaces()];
1311
1312 // Face still exists (is necessary?) and still boundary face
1313 if (newFacei >= 0 && newFacei >= mesh.nInternalFaces())
1314 {
1315 newBoundaryData[newFacei - mesh.nInternalFaces()] =
1316 boundaryData0[oldBFacei];
1317 }
1318 }
1319
1320 forAll(boundaryData1, addedBFacei)
1321 {
1322 label newFacei = map.addedFaceMap()[addedBFacei + nInternalFaces1];
1323
1324 if (newFacei >= 0 && newFacei >= mesh.nInternalFaces())
1325 {
1326 newBoundaryData[newFacei - mesh.nInternalFaces()] =
1327 boundaryData1[addedBFacei];
1328 }
1329 }
1330
1331 return newBoundaryData;
1332}
1333
1334
1335Foam::labelList Foam::fvMeshDistribute::mapPointData
1336(
1337 const primitiveMesh& mesh, // mesh after adding
1338 const mapAddedPolyMesh& map,
1339 const labelList& boundaryData0, // on mesh before adding
1340 const labelList& boundaryData1 // on added mesh
1341)
1342{
1343 labelList newBoundaryData(mesh.nPoints());
1344
1345 forAll(boundaryData0, oldPointi)
1346 {
1347 label newPointi = map.oldPointMap()[oldPointi];
1348
1349 // Point still exists (is necessary?)
1350 if (newPointi >= 0)
1351 {
1352 newBoundaryData[newPointi] = boundaryData0[oldPointi];
1353 }
1354 }
1355
1356 forAll(boundaryData1, addedPointi)
1357 {
1358 label newPointi = map.addedPointMap()[addedPointi];
1359
1360 if (newPointi >= 0)
1361 {
1362 newBoundaryData[newPointi] = boundaryData1[addedPointi];
1363 }
1364 }
1365
1366 return newBoundaryData;
1367}
1368
1369
1370// Remove cells. Add all exposed faces to patch oldInternalPatchi
1371Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
1372(
1373 const labelList& cellsToRemove,
1374 const label oldInternalPatchi
1375)
1376{
1377 // Mesh change engine
1378 polyTopoChange meshMod(mesh_);
1379
1380 // Cell removal topo engine. Do NOT synchronize parallel since
1381 // we are doing a local cell removal.
1382 removeCells cellRemover(mesh_, false);
1383
1384 // Get all exposed faces
1385 labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
1386
1387 // Insert the topo changes
1388 cellRemover.setRefinement
1389 (
1390 cellsToRemove,
1391 exposedFaces,
1392 labelList(exposedFaces.size(), oldInternalPatchi), // patch for exposed
1393 // faces.
1394 meshMod
1395 );
1396
1397
1399 //tmp<surfaceScalarField> sfld(generateTestField(mesh_));
1400
1401 // Save internal fields (note: not as DimensionedFields since would
1402 // get mapped)
1403 PtrList<Field<scalar>> sFlds;
1404 saveInternalFields(sFlds);
1405 PtrList<Field<vector>> vFlds;
1406 saveInternalFields(vFlds);
1407 PtrList<Field<sphericalTensor>> sptFlds;
1408 saveInternalFields(sptFlds);
1409 PtrList<Field<symmTensor>> sytFlds;
1410 saveInternalFields(sytFlds);
1411 PtrList<Field<tensor>> tFlds;
1412 saveInternalFields(tFlds);
1413
1414 // Change the mesh. No inflation. Note: no parallel comms allowed.
1415
1416 // TBD: temporarily unset mesh moving to avoid problems in meshflux
1417 // mapping. To be investigated.
1418 const bool oldMoving = mesh_.moving(false);
1419 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
1420 mesh_.moving(oldMoving);
1421
1422 // Update fields
1423 mesh_.updateMesh(map());
1424
1425
1426 // Any exposed faces in a surfaceField will not be mapped. Map the value
1427 // of these separately (until there is support in all PatchFields for
1428 // mapping from internal faces ...)
1429
1430 mapExposedFaces(map(), sFlds);
1431 mapExposedFaces(map(), vFlds);
1432 mapExposedFaces(map(), sptFlds);
1433 mapExposedFaces(map(), sytFlds);
1434 mapExposedFaces(map(), tFlds);
1435
1436
1438 //testField(sfld);
1439
1440
1441 // Move mesh (since morphing does not do this)
1442 if (map().hasMotionPoints())
1443 {
1444 mesh_.movePoints(map().preMotionPoints());
1445 }
1446
1447
1448 return map;
1449}
1450
1451
1452// Delete and add processor patches. Changes mesh and returns per neighbour proc
1453// the processor patchID.
1454void Foam::fvMeshDistribute::addProcPatches
1455(
1456 const labelList& nbrProc, // processor that neighbour is now on
1457 const labelList& referPatchID, // patchID (or -1) I originated from
1458 List<Map<label>>& procPatchID
1459)
1460{
1461 // Now use the neighbourFace/Proc to repatch the mesh. These lists
1462 // contain for all current boundary faces the global patchID (for non-proc
1463 // patch) or the processor.
1464
1465 // Determine a visit order such that the processor patches get added
1466 // in order of increasing neighbour processor (and for same neighbour
1467 // processor (in case of processor cyclics) in order of increasing
1468 // 'refer' patch)
1469 labelList indices;
1470 sortedOrder(nbrProc, indices, lessProcPatches(nbrProc, referPatchID));
1471
1472 procPatchID.setSize(Pstream::nProcs());
1473
1474 forAll(indices, i)
1475 {
1476 label bFacei = indices[i];
1477 label proci = nbrProc[bFacei];
1478
1479 if (proci != -1 && proci != Pstream::myProcNo())
1480 {
1481 if (!procPatchID[proci].found(referPatchID[bFacei]))
1482 {
1483 // No patch for neighbour yet. Is either a normal processor
1484 // patch or a processorCyclic patch.
1485
1486 if (referPatchID[bFacei] == -1)
1487 {
1488 // Ordinary processor boundary
1489
1490 processorPolyPatch pp
1491 (
1492 0, // size
1493 mesh_.nFaces(),
1494 mesh_.boundaryMesh().size(),
1495 mesh_.boundaryMesh(),
1497 proci
1498 );
1499
1500 procPatchID[proci].insert
1501 (
1502 referPatchID[bFacei],
1504 (
1505 mesh_,
1506 pp,
1507 dictionary(), // optional per field patchField
1509 false // not parallel sync
1510 )
1511 );
1512 }
1513 else
1514 {
1515 const coupledPolyPatch& pcPatch
1516 = refCast<const coupledPolyPatch>
1517 (
1518 mesh_.boundaryMesh()[referPatchID[bFacei]]
1519 );
1520 processorCyclicPolyPatch pp
1521 (
1522 0, // size
1523 mesh_.nFaces(),
1524 mesh_.boundaryMesh().size(),
1525 mesh_.boundaryMesh(),
1527 proci,
1528 pcPatch.name(),
1529 pcPatch.transform()
1530 );
1531
1532 procPatchID[proci].insert
1533 (
1534 referPatchID[bFacei],
1536 (
1537 mesh_,
1538 pp,
1539 dictionary(), // optional per field patchField
1541 false // not parallel sync
1542 )
1543 );
1544 }
1545 }
1546 }
1547 }
1548}
1549
1550
1551// Get boundary faces to be repatched. Is -1 or new patchID
1552Foam::labelList Foam::fvMeshDistribute::getBoundaryPatch
1553(
1554 const labelList& nbrProc, // new processor per boundary face
1555 const labelList& referPatchID, // patchID (or -1) I originated from
1556 const List<Map<label>>& procPatchID // per proc the new procPatches
1557)
1558{
1559 labelList patchIDs(nbrProc);
1560
1561 forAll(nbrProc, bFacei)
1562 {
1563 if (nbrProc[bFacei] == Pstream::myProcNo())
1564 {
1565 label origPatchi = referPatchID[bFacei];
1566 patchIDs[bFacei] = origPatchi;
1567 }
1568 else if (nbrProc[bFacei] != -1)
1569 {
1570 label origPatchi = referPatchID[bFacei];
1571 patchIDs[bFacei] = procPatchID[nbrProc[bFacei]][origPatchi];
1572 }
1573 else
1574 {
1575 patchIDs[bFacei] = -1;
1576 }
1577 }
1578 return patchIDs;
1579}
1580
1581
1582// Send mesh and coupling data.
1583void Foam::fvMeshDistribute::sendMesh
1584(
1585 const label domain,
1586 const fvMesh& mesh,
1587
1588 const wordList& pointZoneNames,
1589 const wordList& faceZoneNames,
1590 const wordList& cellZoneNames,
1591
1592 const labelList& sourceFace,
1593 const labelList& sourceProc,
1594 const labelList& sourcePatch,
1595 const labelList& sourceNewNbrProc,
1596 const labelList& sourcePointMaster,
1597 Ostream& toDomain
1598)
1599{
1600 if (debug)
1601 {
1602 Pout<< "Sending to domain " << domain << nl
1603 << " nPoints:" << mesh.nPoints() << nl
1604 << " nFaces:" << mesh.nFaces() << nl
1605 << " nCells:" << mesh.nCells() << nl
1606 << " nPatches:" << mesh.boundaryMesh().size() << nl
1607 << endl;
1608 }
1609
1610 // Assume sparse, possibly overlapping point zones. Get contents
1611 // in merged-zone indices.
1612 CompactListList<label> zonePoints;
1613 {
1614 const pointZoneMesh& pointZones = mesh.pointZones();
1615
1616 labelList rowSizes(pointZoneNames.size(), Zero);
1617
1618 forAll(pointZoneNames, nameI)
1619 {
1620 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1621
1622 if (myZoneID != -1)
1623 {
1624 rowSizes[nameI] = pointZones[myZoneID].size();
1625 }
1626 }
1627 zonePoints.setSize(rowSizes);
1628
1629 forAll(pointZoneNames, nameI)
1630 {
1631 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1632
1633 if (myZoneID != -1)
1634 {
1635 zonePoints[nameI].deepCopy(pointZones[myZoneID]);
1636 }
1637 }
1638 }
1639
1640 // Assume sparse, possibly overlapping face zones
1641 CompactListList<label> zoneFaces;
1642 CompactListList<bool> zoneFaceFlip;
1643 {
1644 const faceZoneMesh& faceZones = mesh.faceZones();
1645
1646 labelList rowSizes(faceZoneNames.size(), Zero);
1647
1648 forAll(faceZoneNames, nameI)
1649 {
1650 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1651
1652 if (myZoneID != -1)
1653 {
1654 rowSizes[nameI] = faceZones[myZoneID].size();
1655 }
1656 }
1657
1658 zoneFaces.setSize(rowSizes);
1659 zoneFaceFlip.setSize(rowSizes);
1660
1661 forAll(faceZoneNames, nameI)
1662 {
1663 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1664
1665 if (myZoneID != -1)
1666 {
1667 zoneFaces[nameI].deepCopy(faceZones[myZoneID]);
1668 zoneFaceFlip[nameI].deepCopy(faceZones[myZoneID].flipMap());
1669 }
1670 }
1671 }
1672
1673 // Assume sparse, possibly overlapping cell zones
1674 CompactListList<label> zoneCells;
1675 {
1676 const cellZoneMesh& cellZones = mesh.cellZones();
1677
1678 labelList rowSizes(cellZoneNames.size(), Zero);
1679
1680 forAll(cellZoneNames, nameI)
1681 {
1682 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1683
1684 if (myZoneID != -1)
1685 {
1686 rowSizes[nameI] = cellZones[myZoneID].size();
1687 }
1688 }
1689
1690 zoneCells.setSize(rowSizes);
1691
1692 forAll(cellZoneNames, nameI)
1693 {
1694 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1695
1696 if (myZoneID != -1)
1697 {
1698 zoneCells[nameI].deepCopy(cellZones[myZoneID]);
1699 }
1700 }
1701 }
1703 //labelList cellZoneID;
1704 //if (hasCellZones)
1705 //{
1706 // cellZoneID.setSize(mesh.nCells());
1707 // cellZoneID = -1;
1708 //
1709 // const cellZoneMesh& cellZones = mesh.cellZones();
1710 //
1711 // forAll(cellZones, zoneI)
1712 // {
1713 // labelUIndList(cellZoneID, cellZones[zoneI]) = zoneI;
1714 // }
1715 //}
1716
1717 // Send
1718 toDomain
1719 << mesh.points()
1720 // Send as (offsets/values)
1721 << CompactListList<label>::pack<face>(mesh.faces())
1722 << mesh.faceOwner()
1723 << mesh.faceNeighbour()
1724 << mesh.boundaryMesh()
1725
1726 << zonePoints
1727 << zoneFaces
1728 << zoneFaceFlip
1729 << zoneCells
1730
1731 << sourceFace
1732 << sourceProc
1733 << sourcePatch
1734 << sourceNewNbrProc
1735 << sourcePointMaster;
1736
1737
1738 if (debug)
1739 {
1740 Pout<< "Started sending mesh to domain " << domain
1741 << endl;
1742 }
1743}
1744
1745
1746// Receive mesh. Opposite of sendMesh
1747Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
1748(
1749 const label domain,
1750 const wordList& pointZoneNames,
1751 const wordList& faceZoneNames,
1752 const wordList& cellZoneNames,
1753 const Time& runTime,
1754 labelList& domainSourceFace,
1755 labelList& domainSourceProc,
1756 labelList& domainSourcePatch,
1757 labelList& domainSourceNewNbrProc,
1758 labelList& domainSourcePointMaster,
1759 Istream& fromNbr
1760)
1761{
1762 pointField domainPoints(fromNbr);
1763 // Receive as (offsets/values), unpack to faceList
1764 faceList domainFaces = CompactListList<label>(fromNbr).unpack<face>();
1765 labelList domainAllOwner(fromNbr);
1766 labelList domainAllNeighbour(fromNbr);
1767 PtrList<entry> patchEntries(fromNbr);
1768
1769 CompactListList<label> zonePoints(fromNbr);
1770 CompactListList<label> zoneFaces(fromNbr);
1771 CompactListList<bool> zoneFaceFlip(fromNbr);
1772 CompactListList<label> zoneCells(fromNbr);
1773
1774 fromNbr
1775 >> domainSourceFace
1776 >> domainSourceProc
1777 >> domainSourcePatch
1778 >> domainSourceNewNbrProc
1779 >> domainSourcePointMaster;
1780
1781 // Construct fvMesh
1782 auto domainMeshPtr = autoPtr<fvMesh>::New
1783 (
1784 IOobject
1785 (
1787 runTime.timeName(),
1788 runTime,
1790 ),
1791 std::move(domainPoints),
1792 std::move(domainFaces),
1793 std::move(domainAllOwner),
1794 std::move(domainAllNeighbour),
1795 false // no parallel comms
1796 );
1797 fvMesh& domainMesh = *domainMeshPtr;
1798
1799 List<polyPatch*> patches(patchEntries.size());
1800
1801 forAll(patchEntries, patchi)
1802 {
1803 patches[patchi] = polyPatch::New
1804 (
1805 patchEntries[patchi].keyword(),
1806 patchEntries[patchi].dict(),
1807 patchi,
1808 domainMesh.boundaryMesh()
1809 ).ptr();
1810 }
1811 // Add patches; no parallel comms
1812 domainMesh.addFvPatches(patches, false);
1813
1814 // Construct zones
1815 List<pointZone*> pZonePtrs(pointZoneNames.size());
1816 forAll(pZonePtrs, i)
1817 {
1818 pZonePtrs[i] = new pointZone
1819 (
1820 pointZoneNames[i],
1821 zonePoints[i],
1822 i,
1823 domainMesh.pointZones()
1824 );
1825 }
1826
1827 List<faceZone*> fZonePtrs(faceZoneNames.size());
1828 forAll(fZonePtrs, i)
1829 {
1830 fZonePtrs[i] = new faceZone
1831 (
1832 faceZoneNames[i],
1833 zoneFaces[i],
1834 zoneFaceFlip[i],
1835 i,
1836 domainMesh.faceZones()
1837 );
1838 }
1839
1840 List<cellZone*> cZonePtrs(cellZoneNames.size());
1841 forAll(cZonePtrs, i)
1842 {
1843 cZonePtrs[i] = new cellZone
1844 (
1845 cellZoneNames[i],
1846 zoneCells[i],
1847 i,
1848 domainMesh.cellZones()
1849 );
1850 }
1851 domainMesh.addZones(pZonePtrs, fZonePtrs, cZonePtrs);
1852
1853 return domainMeshPtr;
1854}
1855
1856
1857// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1858
1860:
1861 mesh_(mesh)
1862{}
1863
1864
1865// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1866
1868(
1869 const labelList& distribution
1870)
1871{
1872 labelList nCells(Pstream::nProcs(), Zero);
1873 forAll(distribution, celli)
1874 {
1875 label newProc = distribution[celli];
1876
1877 if (newProc < 0 || newProc >= Pstream::nProcs())
1878 {
1880 << "Distribution should be in range 0.." << Pstream::nProcs()-1
1881 << endl
1882 << "At index " << celli << " distribution:" << newProc
1883 << abort(FatalError);
1884 }
1885 nCells[newProc]++;
1886 }
1887 return nCells;
1888}
1889
1890
1892(
1893 const labelList& distribution
1894)
1895{
1896 // Some checks on distribution
1897 if (distribution.size() != mesh_.nCells())
1898 {
1900 << "Size of distribution:"
1901 << distribution.size() << " mesh nCells:" << mesh_.nCells()
1902 << abort(FatalError);
1903 }
1904
1905
1906 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1907
1908 // Check all processors have same non-proc patches in same order.
1909 if (patches.checkParallelSync(true))
1910 {
1912 << "This application requires all non-processor patches"
1913 << " to be present in the same order on all patches" << nl
1914 << "followed by the processor patches (which of course are unique)."
1915 << nl
1916 << "Local patches:" << mesh_.boundaryMesh().names()
1917 << abort(FatalError);
1918 }
1919
1920 // Save some data for mapping later on
1921 const label nOldPoints(mesh_.nPoints());
1922 const label nOldFaces(mesh_.nFaces());
1923 const label nOldCells(mesh_.nCells());
1924 labelList oldPatchStarts(patches.size());
1925 labelList oldPatchNMeshPoints(patches.size());
1926 forAll(patches, patchi)
1927 {
1928 oldPatchStarts[patchi] = patches[patchi].start();
1929 oldPatchNMeshPoints[patchi] = patches[patchi].nPoints();
1930 }
1931
1932
1933
1934 // Short circuit trivial case.
1935 if (!Pstream::parRun())
1936 {
1937 // Collect all maps and return
1939 (
1940 mesh_,
1941
1942 nOldPoints,
1943 nOldFaces,
1944 nOldCells,
1945 std::move(oldPatchStarts),
1946 std::move(oldPatchNMeshPoints),
1947
1948 labelListList(one(), identity(mesh_.nPoints())), //subPointMap
1949 labelListList(one(), identity(mesh_.nFaces())), //subFaceMap
1950 labelListList(one(), identity(mesh_.nCells())), //subCellMap
1951 labelListList(one(), identity(patches.size())), //subPatchMap
1952
1953 labelListList(one(), identity(mesh_.nPoints())), //pointMap
1954 labelListList(one(), identity(mesh_.nFaces())), //faceMap
1955 labelListList(one(), identity(mesh_.nCells())), //cellMap
1956 labelListList(one(), identity(patches.size())) //patchMap
1957 );
1958 }
1959
1960
1961 // Collect any zone names over all processors and shuffle zones accordingly
1962 // Note that this is not necessary for redistributePar since that already
1963 // checks for it. However other use (e.g. mesh generators) might not.
1964 const wordList pointZoneNames(mergeWordList(mesh_.pointZones().names()));
1965 reorderZones<pointZone>(pointZoneNames, mesh_.pointZones());
1966
1967 const wordList faceZoneNames(mergeWordList(mesh_.faceZones().names()));
1968 reorderZones<faceZone>(faceZoneNames, mesh_.faceZones());
1969
1970 const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
1971 reorderZones<cellZone>(cellZoneNames, mesh_.cellZones());
1972
1973
1974 // Local environment of all boundary faces
1975 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1976
1977 // A face is uniquely defined by
1978 // - proc
1979 // - local face no
1980 //
1981 // To glue the parts of meshes which can get sent from anywhere we
1982 // need to know on boundary faces what the above tuple on both sides is.
1983 // So we need to maintain:
1984 // - original face
1985 // - original processor id (= trivial)
1986 // For coupled boundaries (where the faces are 'duplicate') we take the
1987 // lowest numbered processor as the data to store.
1988 //
1989 // Additionally to create the procboundaries we need to know where the owner
1990 // cell on the other side now is: newNeighbourProc.
1991 //
1992
1993 // physical boundary:
1994 // sourceProc = -1
1995 // sourceNewNbrProc = -1
1996 // sourceFace = -1
1997 // sourcePatch = patchID
1998 // processor boundary:
1999 // sourceProc = proc (on owner side)
2000 // sourceNewNbrProc = distribution of coupled cell
2001 // sourceFace = face (on owner side)
2002 // sourcePatch = -1
2003 // ?cyclic:
2004 // ? sourceProc = proc
2005 // ? sourceNewNbrProc = distribution of coupled cell
2006 // ? sourceFace = face (on owner side)
2007 // ? sourcePatch = patchID
2008 // processor-cyclic boundary:
2009 // sourceProc = proc (on owner side)
2010 // sourceNewNbrProc = distribution of coupled cell
2011 // sourceFace = face (on owner side)
2012 // sourcePatch = patchID
2013
2014 labelList sourcePatch;
2015 labelList sourceFace;
2016 labelList sourceProc;
2017 labelList sourceNewNbrProc;
2018 labelList sourcePointMaster;
2019 getCouplingData
2020 (
2022 sourceFace,
2023 sourceProc,
2024 sourcePatch,
2025 sourceNewNbrProc,
2026 sourcePointMaster
2027 );
2028
2029
2030 // Remove meshPhi. Since this would otherwise disappear anyway
2031 // during topo changes and we have to guarantee that all the fields
2032 // can be sent.
2033 mesh_.clearOut();
2034 mesh_.resetMotion();
2035
2036 // Get data to send. Make sure is synchronised
2037
2038 HashTable<wordList> allFieldNames;
2039
2040 getFieldNames<volScalarField>(mesh_, allFieldNames);
2041 getFieldNames<volVectorField>(mesh_, allFieldNames);
2042 getFieldNames<volSphericalTensorField>(mesh_, allFieldNames);
2043 getFieldNames<volSymmTensorField>(mesh_, allFieldNames);
2044 getFieldNames<volTensorField>(mesh_, allFieldNames);
2045
2046 getFieldNames<surfaceScalarField>(mesh_, allFieldNames);
2047 getFieldNames<surfaceVectorField>(mesh_, allFieldNames);
2048 getFieldNames<surfaceSphericalTensorField>(mesh_, allFieldNames);
2049 getFieldNames<surfaceSymmTensorField>(mesh_, allFieldNames);
2050 getFieldNames<surfaceTensorField>(mesh_, allFieldNames);
2051
2052 getFieldNames<volScalarField::Internal>
2053 (
2054 mesh_,
2055 allFieldNames,
2057 );
2058 getFieldNames<volVectorField::Internal>
2059 (
2060 mesh_,
2061 allFieldNames,
2063 );
2064 getFieldNames<volSphericalTensorField::Internal>
2065 (
2066 mesh_,
2067 allFieldNames,
2069 );
2070 getFieldNames<volSymmTensorField::Internal>
2071 (
2072 mesh_,
2073 allFieldNames,
2075 );
2076 getFieldNames<volTensorField::Internal>
2077 (
2078 mesh_,
2079 allFieldNames,
2081 );
2082
2083
2084 // Find patch to temporarily put exposed and processor faces into.
2085 const label oldInternalPatchi = findNonEmptyPatch();
2086
2087
2088 // Delete processor patches, starting from the back. Move all faces into
2089 // oldInternalPatchi.
2090 labelList repatchFaceMap;
2091 {
2092 autoPtr<mapPolyMesh> repatchMap = deleteProcPatches(oldInternalPatchi);
2093
2094 // Store face map (only face ordering that changed)
2095 repatchFaceMap = repatchMap().faceMap();
2096
2097 // Reorder all boundary face data (sourceProc, sourceFace etc.)
2098 labelList bFaceMap
2099 (
2101 (
2102 repatchMap().reverseFaceMap(),
2103 mesh_.nBoundaryFaces(),
2104 mesh_.nInternalFaces()
2105 )
2106 - mesh_.nInternalFaces()
2107 );
2108
2109 inplaceReorder(bFaceMap, sourceFace);
2110 inplaceReorder(bFaceMap, sourceProc);
2111 inplaceReorder(bFaceMap, sourcePatch);
2112 inplaceReorder(bFaceMap, sourceNewNbrProc);
2113 }
2114
2115
2116
2117 // Print a bit.
2118 if (debug)
2119 {
2120 Pout<< nl << "MESH WITH PROC PATCHES DELETED:" << endl;
2121 printMeshInfo(mesh_);
2122 printFieldInfo<volScalarField>(mesh_);
2123 printFieldInfo<volVectorField>(mesh_);
2124 printFieldInfo<volSphericalTensorField>(mesh_);
2125 printFieldInfo<volSymmTensorField>(mesh_);
2126 printFieldInfo<volTensorField>(mesh_);
2127 printFieldInfo<surfaceScalarField>(mesh_);
2128 printFieldInfo<surfaceVectorField>(mesh_);
2129 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2130 printFieldInfo<surfaceSymmTensorField>(mesh_);
2131 printFieldInfo<surfaceTensorField>(mesh_);
2132 printIntFieldInfo<volScalarField::Internal>(mesh_);
2133 printIntFieldInfo<volVectorField::Internal>(mesh_);
2134 printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
2135 printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
2136 printIntFieldInfo<volTensorField::Internal>(mesh_);
2137 Pout<< nl << endl;
2138 }
2139
2140
2141
2142 // Maps from subsetted mesh (that is sent) back to original maps
2143 labelListList subCellMap(Pstream::nProcs());
2144 labelListList subFaceMap(Pstream::nProcs());
2145 labelListList subPointMap(Pstream::nProcs());
2146 labelListList subPatchMap(Pstream::nProcs());
2147 // Maps from subsetted mesh to reconstructed mesh
2148 labelListList constructCellMap(Pstream::nProcs());
2149 labelListList constructFaceMap(Pstream::nProcs());
2150 labelListList constructPointMap(Pstream::nProcs());
2151 labelListList constructPatchMap(Pstream::nProcs());
2152
2153
2154 // Find out schedule
2155 // ~~~~~~~~~~~~~~~~~
2156
2157 labelList nSendCells(countCells(distribution));
2158 labelList nRevcCells(Pstream::nProcs());
2159 Pstream::allToAll(nSendCells, nRevcCells);
2160
2161 // Allocate buffers
2163
2164
2165 // What to send to neighbouring domains
2166 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2167
2168 // Disable parallel.
2169 const bool oldParRun = UPstream::parRun(false);
2170
2171 forAll(nSendCells, recvProc)
2172 {
2173 if (recvProc != Pstream::myProcNo() && nSendCells[recvProc] > 0)
2174 {
2175 // Send to recvProc
2176
2177 if (debug)
2178 {
2179 Pout<< nl
2180 << "SUBSETTING FOR DOMAIN " << recvProc
2181 << " cells to send:"
2182 << nSendCells[recvProc]
2183 << nl << endl;
2184 }
2185
2186 // Pstream for sending mesh and fields
2187 //OPstream str(Pstream::commsTypes::blocking, recvProc);
2188 UOPstream str(recvProc, pBufs);
2189
2190 // Mesh subsetting engine - subset the cells of the current domain.
2191 fvMeshSubset subsetter
2192 (
2193 mesh_,
2194 recvProc,
2196 oldInternalPatchi, // oldInternalFaces patch
2197 false // no parallel sync
2198 );
2199
2200 subCellMap[recvProc] = subsetter.cellMap();
2201 subFaceMap[recvProc] = subsetter.faceFlipMap();
2202 inplaceRenumberWithFlip
2203 (
2204 repatchFaceMap,
2205 false, // oldToNew has flip
2206 true, // subFaceMap has flip
2207 subFaceMap[recvProc]
2208 );
2209 subPointMap[recvProc] = subsetter.pointMap();
2210 subPatchMap[recvProc] = subsetter.patchMap();
2211
2212
2213 // Subset the boundary fields (owner/neighbour/processor)
2214 labelList procSourceFace;
2215 labelList procSourceProc;
2216 labelList procSourcePatch;
2217 labelList procSourceNewNbrProc;
2218 labelList procSourcePointMaster;
2219
2220 subsetCouplingData
2221 (
2222 subsetter.subMesh(),
2223 subsetter.pointMap(), // from subMesh to mesh
2224 subsetter.faceMap(), // ,, ,,
2225 subsetter.cellMap(), // ,, ,,
2226
2227 distribution, // old mesh distribution
2228 mesh_.faceOwner(), // old owner
2229 mesh_.faceNeighbour(),
2230 mesh_.nInternalFaces(),
2231
2232 sourceFace,
2233 sourceProc,
2234 sourcePatch,
2235 sourceNewNbrProc,
2236 sourcePointMaster,
2237
2238 procSourceFace,
2239 procSourceProc,
2240 procSourcePatch,
2241 procSourceNewNbrProc,
2242 procSourcePointMaster
2243 );
2244
2245
2246 // Send to neighbour
2247 sendMesh
2248 (
2249 recvProc,
2250 subsetter.subMesh(),
2251
2252 pointZoneNames,
2253 faceZoneNames,
2254 cellZoneNames,
2255
2256 procSourceFace,
2257 procSourceProc,
2258 procSourcePatch,
2259 procSourceNewNbrProc,
2260 procSourcePointMaster,
2261
2262 str
2263 );
2264
2265 // volFields
2266 sendFields<volScalarField>
2267 (
2268 recvProc,
2269 allFieldNames,
2270 subsetter,
2271 str
2272 );
2273 sendFields<volVectorField>
2274 (
2275 recvProc,
2276 allFieldNames,
2277 subsetter,
2278 str
2279 );
2280 sendFields<volSphericalTensorField>
2281 (
2282 recvProc,
2283 allFieldNames,
2284 subsetter,
2285 str
2286 );
2287 sendFields<volSymmTensorField>
2288 (
2289 recvProc,
2290 allFieldNames,
2291 subsetter,
2292 str
2293 );
2294 sendFields<volTensorField>
2295 (
2296 recvProc,
2297 allFieldNames,
2298 subsetter,
2299 str
2300 );
2301
2302 // surfaceFields
2303 sendFields<surfaceScalarField>
2304 (
2305 recvProc,
2306 allFieldNames,
2307 subsetter,
2308 str
2309 );
2310 sendFields<surfaceVectorField>
2311 (
2312 recvProc,
2313 allFieldNames,
2314 subsetter,
2315 str
2316 );
2317 sendFields<surfaceSphericalTensorField>
2318 (
2319 recvProc,
2320 allFieldNames,
2321 subsetter,
2322 str
2323 );
2324 sendFields<surfaceSymmTensorField>
2325 (
2326 recvProc,
2327 allFieldNames,
2328 subsetter,
2329 str
2330 );
2331 sendFields<surfaceTensorField>
2332 (
2333 recvProc,
2334 allFieldNames,
2335 subsetter,
2336 str
2337 );
2338
2339 // Dimensioned fields
2340 sendFields<volScalarField::Internal>
2341 (
2342 recvProc,
2343 allFieldNames,
2344 subsetter,
2345 str
2346 );
2347 sendFields<volVectorField::Internal>
2348 (
2349 recvProc,
2350 allFieldNames,
2351 subsetter,
2352 str
2353 );
2354 sendFields<volSphericalTensorField::Internal>
2355 (
2356 recvProc,
2357 allFieldNames,
2358 subsetter,
2359 str
2360 );
2361 sendFields<volSymmTensorField::Internal>
2362 (
2363 recvProc,
2364 allFieldNames,
2365 subsetter,
2366 str
2367 );
2368 sendFields<volTensorField::Internal>
2369 (
2370 recvProc,
2371 allFieldNames,
2372 subsetter,
2373 str
2374 );
2375 }
2376 }
2377
2378
2379 UPstream::parRun(oldParRun); // Restore parallel state
2380
2381
2382 // Start sending&receiving from buffers
2383 {
2384 if (debug)
2385 {
2386 Pout<< "Starting sending" << endl;
2387 }
2388
2389 labelList recvSizes;
2390 pBufs.finishedSends(recvSizes);
2391
2392 if (debug)
2393 {
2394 Pout<< "Finished sending and receiving : " << flatOutput(recvSizes)
2395 << endl;
2396 }
2397 }
2398
2399
2400 // Subset the part that stays
2401 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
2402
2403 {
2404 // Save old mesh maps before changing mesh
2405 const labelList oldFaceOwner(mesh_.faceOwner());
2406 const labelList oldFaceNeighbour(mesh_.faceNeighbour());
2407 const label oldInternalFaces = mesh_.nInternalFaces();
2408
2409 // Remove cells.
2411 (
2412 doRemoveCells
2413 (
2414 select(false, distribution, Pstream::myProcNo()),
2415 oldInternalPatchi
2416 )
2417 );
2418
2419 // Addressing from subsetted mesh
2420 subCellMap[Pstream::myProcNo()] = subMap().cellMap();
2421 subFaceMap[Pstream::myProcNo()] = renumber
2422 (
2423 repatchFaceMap,
2424 subMap().faceMap()
2425 );
2426 // Insert the sign bit from face flipping
2427 labelList& faceMap = subFaceMap[Pstream::myProcNo()];
2428 forAll(faceMap, faceI)
2429 {
2430 faceMap[faceI] += 1;
2431 }
2432 const labelHashSet& flip = subMap().flipFaceFlux();
2433 for (const label facei : flip)
2434 {
2435 faceMap[facei] = -faceMap[facei];
2436 }
2437 subPointMap[Pstream::myProcNo()] = subMap().pointMap();
2438 subPatchMap[Pstream::myProcNo()] = identity(patches.size());
2439
2440 // Subset the mesh data: neighbourCell/neighbourProc fields
2441 labelList domainSourceFace;
2442 labelList domainSourceProc;
2443 labelList domainSourcePatch;
2444 labelList domainSourceNewNbrProc;
2445 labelList domainSourcePointMaster;
2446
2447 subsetCouplingData
2448 (
2449 mesh_, // new mesh
2450 subMap().pointMap(), // from new to original mesh
2451 subMap().faceMap(), // from new to original mesh
2452 subMap().cellMap(),
2453
2454 distribution, // distribution before subsetting
2455 oldFaceOwner, // owner before subsetting
2456 oldFaceNeighbour, // neighbour ,,
2457 oldInternalFaces, // nInternalFaces ,,
2458
2459 sourceFace,
2460 sourceProc,
2461 sourcePatch,
2462 sourceNewNbrProc,
2463 sourcePointMaster,
2464
2465 domainSourceFace,
2466 domainSourceProc,
2467 domainSourcePatch,
2468 domainSourceNewNbrProc,
2469 domainSourcePointMaster
2470 );
2471
2472 sourceFace.transfer(domainSourceFace);
2473 sourceProc.transfer(domainSourceProc);
2474 sourcePatch.transfer(domainSourcePatch);
2475 sourceNewNbrProc.transfer(domainSourceNewNbrProc);
2476 sourcePointMaster.transfer(domainSourcePointMaster);
2477 }
2478
2479
2480 // Print a bit.
2481 if (debug)
2482 {
2483 Pout<< nl << "STARTING MESH:" << endl;
2484 printMeshInfo(mesh_);
2485 printFieldInfo<volScalarField>(mesh_);
2486 printFieldInfo<volVectorField>(mesh_);
2487 printFieldInfo<volSphericalTensorField>(mesh_);
2488 printFieldInfo<volSymmTensorField>(mesh_);
2489 printFieldInfo<volTensorField>(mesh_);
2490 printFieldInfo<surfaceScalarField>(mesh_);
2491 printFieldInfo<surfaceVectorField>(mesh_);
2492 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2493 printFieldInfo<surfaceSymmTensorField>(mesh_);
2494 printFieldInfo<surfaceTensorField>(mesh_);
2495 printIntFieldInfo<volScalarField::Internal>(mesh_);
2496 printIntFieldInfo<volVectorField::Internal>(mesh_);
2497 printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
2498 printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
2499 printIntFieldInfo<volTensorField::Internal>(mesh_);
2500 Pout<< nl << endl;
2501 }
2502
2503
2504
2505 // Receive and add what was sent
2506 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2507
2508 // Disable parallel. Original state already known.
2509 UPstream::parRun(false);
2510
2511 PtrList<labelList> domainSourceFaces(Pstream::nProcs());
2512 PtrList<labelList> domainSourceProcs(Pstream::nProcs());
2513 PtrList<labelList> domainSourcePatchs(Pstream::nProcs());
2514 PtrList<labelList> domainSourceNewNbrProcs(Pstream::nProcs());
2515 PtrList<labelList> domainSourcePointMasters(Pstream::nProcs());
2516
2517 PtrList<fvMesh> domainMeshPtrs(Pstream::nProcs());
2518
2524
2528 (
2530 );
2533
2537 (
2539 );
2541 (
2543 );
2545
2546 forAll(nRevcCells, sendProc)
2547 {
2548 // Did processor sendProc send anything to me?
2549 if (sendProc != Pstream::myProcNo() && nRevcCells[sendProc] > 0)
2550 {
2551 if (debug)
2552 {
2553 Pout<< nl
2554 << "RECEIVING FROM DOMAIN " << sendProc
2555 << " cells to receive:"
2556 << nRevcCells[sendProc]
2557 << nl << endl;
2558 }
2559
2560
2561 // Pstream for receiving mesh and fields
2562 UIPstream str(sendProc, pBufs);
2563
2564
2565 // Receive from sendProc
2566 domainSourceFaces.set(sendProc, new labelList(0));
2567 labelList& domainSourceFace = domainSourceFaces[sendProc];
2568
2569 domainSourceProcs.set(sendProc, new labelList(0));
2570 labelList& domainSourceProc = domainSourceProcs[sendProc];
2571
2572 domainSourcePatchs.set(sendProc, new labelList(0));
2573 labelList& domainSourcePatch = domainSourcePatchs[sendProc];
2574
2575 domainSourceNewNbrProcs.set(sendProc, new labelList(0));
2576 labelList& domainSourceNewNbrProc =
2577 domainSourceNewNbrProcs[sendProc];
2578
2579 domainSourcePointMasters.set(sendProc, new labelList(0));
2580 labelList& domainSourcePointMaster =
2581 domainSourcePointMasters[sendProc];
2582
2583 // Opposite of sendMesh
2584 {
2585 autoPtr<fvMesh> domainMeshPtr = receiveMesh
2586 (
2587 sendProc,
2588 pointZoneNames,
2589 faceZoneNames,
2590 cellZoneNames,
2591
2592 const_cast<Time&>(mesh_.time()),
2593 domainSourceFace,
2594 domainSourceProc,
2595 domainSourcePatch,
2596 domainSourceNewNbrProc,
2597 domainSourcePointMaster,
2598 str
2599 );
2600 domainMeshPtrs.set(sendProc, domainMeshPtr.ptr());
2601 fvMesh& domainMesh = domainMeshPtrs[sendProc];
2602 // Force construction of various on mesh.
2603 //(void)domainMesh.globalData();
2604
2605
2606 // Receive fields. Read as single dictionary because
2607 // of problems reading consecutive fields from single stream.
2608 dictionary fieldDicts(str);
2609
2610 // Vol fields
2611 vsfs.set(sendProc, new PtrList<volScalarField>(0));
2612 receiveFields<volScalarField>
2613 (
2614 sendProc,
2615 allFieldNames,
2616 domainMesh,
2617 vsfs[sendProc],
2618 fieldDicts
2619 );
2620 vvfs.set(sendProc, new PtrList<volVectorField>(0));
2621 receiveFields<volVectorField>
2622 (
2623 sendProc,
2624 allFieldNames,
2625 domainMesh,
2626 vvfs[sendProc],
2627 fieldDicts
2628 );
2629 vsptfs.set
2630 (
2631 sendProc,
2633 );
2634 receiveFields<volSphericalTensorField>
2635 (
2636 sendProc,
2637 allFieldNames,
2638 domainMesh,
2639 vsptfs[sendProc],
2640 fieldDicts
2641 );
2642 vsytfs.set(sendProc, new PtrList<volSymmTensorField>(0));
2643 receiveFields<volSymmTensorField>
2644 (
2645 sendProc,
2646 allFieldNames,
2647 domainMesh,
2648 vsytfs[sendProc],
2649 fieldDicts
2650 );
2651 vtfs.set(sendProc, new PtrList<volTensorField>(0));
2652 receiveFields<volTensorField>
2653 (
2654 sendProc,
2655 allFieldNames,
2656 domainMesh,
2657 vtfs[sendProc],
2658 fieldDicts
2659 );
2660
2661 // Surface fields
2662 ssfs.set(sendProc, new PtrList<surfaceScalarField>(0));
2663 receiveFields<surfaceScalarField>
2664 (
2665 sendProc,
2666 allFieldNames,
2667 domainMesh,
2668 ssfs[sendProc],
2669 fieldDicts
2670 );
2671 svfs.set(sendProc, new PtrList<surfaceVectorField>(0));
2672 receiveFields<surfaceVectorField>
2673 (
2674 sendProc,
2675 allFieldNames,
2676 domainMesh,
2677 svfs[sendProc],
2678 fieldDicts
2679 );
2680 ssptfs.set
2681 (
2682 sendProc,
2684 );
2685 receiveFields<surfaceSphericalTensorField>
2686 (
2687 sendProc,
2688 allFieldNames,
2689 domainMesh,
2690 ssptfs[sendProc],
2691 fieldDicts
2692 );
2693 ssytfs.set(sendProc, new PtrList<surfaceSymmTensorField>(0));
2694 receiveFields<surfaceSymmTensorField>
2695 (
2696 sendProc,
2697 allFieldNames,
2698 domainMesh,
2699 ssytfs[sendProc],
2700 fieldDicts
2701 );
2702 stfs.set(sendProc, new PtrList<surfaceTensorField>(0));
2703 receiveFields<surfaceTensorField>
2704 (
2705 sendProc,
2706 allFieldNames,
2707 domainMesh,
2708 stfs[sendProc],
2709 fieldDicts
2710 );
2711
2712 // Dimensioned fields
2713 dsfs.set
2714 (
2715 sendProc,
2717 );
2718 receiveFields<volScalarField::Internal>
2719 (
2720 sendProc,
2721 allFieldNames,
2722 domainMesh,
2723 dsfs[sendProc],
2724 fieldDicts
2725 );
2726 dvfs.set
2727 (
2728 sendProc,
2730 );
2731 receiveFields<volVectorField::Internal>
2732 (
2733 sendProc,
2734 allFieldNames,
2735 domainMesh,
2736 dvfs[sendProc],
2737 fieldDicts
2738 );
2739 dstfs.set
2740 (
2741 sendProc,
2743 );
2744 receiveFields<volSphericalTensorField::Internal>
2745 (
2746 sendProc,
2747 allFieldNames,
2748 domainMesh,
2749 dstfs[sendProc],
2750 fieldDicts
2751 );
2752 dsytfs.set
2753 (
2754 sendProc,
2756 );
2757 receiveFields<volSymmTensorField::Internal>
2758 (
2759 sendProc,
2760 allFieldNames,
2761 domainMesh,
2762 dsytfs[sendProc],
2763 fieldDicts
2764 );
2765 dtfs.set
2766 (
2767 sendProc,
2769 );
2770 receiveFields<volTensorField::Internal>
2771 (
2772 sendProc,
2773 allFieldNames,
2774 domainMesh,
2775 dtfs[sendProc],
2776 fieldDicts
2777 );
2778 }
2779 }
2780 }
2781
2782 // Clear out storage
2783 pBufs.clear();
2784
2785
2786 // Set up pointers to meshes so we can include our mesh_
2787 UPtrList<polyMesh> meshes(domainMeshPtrs.size());
2788 UPtrList<fvMesh> fvMeshes(domainMeshPtrs.size());
2789 forAll(domainMeshPtrs, proci)
2790 {
2791 if (domainMeshPtrs.set(proci))
2792 {
2793 meshes.set(proci, &domainMeshPtrs[proci]);
2794 fvMeshes.set(proci, &domainMeshPtrs[proci]);
2795 }
2796 }
2797
2798 // 'Receive' from myself
2799 {
2800 meshes.set(Pstream::myProcNo(), &mesh_);
2801 fvMeshes.set(Pstream::myProcNo(), &mesh_);
2802
2803 //domainSourceFaces.set(Pstream::myProcNo(), std::move(sourceFace));
2804 domainSourceFaces.set(Pstream::myProcNo(), new labelList(0));
2805 domainSourceFaces[Pstream::myProcNo()] = sourceFace;
2806
2807 domainSourceProcs.set(Pstream::myProcNo(), new labelList(0));
2808 //std::move(sourceProc));
2809 domainSourceProcs[Pstream::myProcNo()] = sourceProc;
2810
2811 domainSourcePatchs.set(Pstream::myProcNo(), new labelList(0));
2812 //, std::move(sourcePatch));
2813 domainSourcePatchs[Pstream::myProcNo()] = sourcePatch;
2814
2815 domainSourceNewNbrProcs.set(Pstream::myProcNo(), new labelList(0));
2816 domainSourceNewNbrProcs[Pstream::myProcNo()] = sourceNewNbrProc;
2817
2818 domainSourcePointMasters.set(Pstream::myProcNo(), new labelList(0));
2819 domainSourcePointMasters[Pstream::myProcNo()] = sourcePointMaster;
2820 }
2821
2822
2823 // Find matching faces that need to be stitched
2824 labelListList localBoundaryFace(Pstream::nProcs());
2825 labelListList remoteFaceProc(Pstream::nProcs());
2826 labelListList remoteBoundaryFace(Pstream::nProcs());
2827 findCouples
2828 (
2829 meshes,
2830 domainSourceFaces,
2831 domainSourceProcs,
2832 domainSourcePatchs,
2833
2834 localBoundaryFace,
2835 remoteFaceProc,
2836 remoteBoundaryFace
2837 );
2838
2839
2840 const label nOldInternalFaces = mesh_.nInternalFaces();
2841 const labelList oldFaceOwner(mesh_.faceOwner());
2842
2843 // TBD: temporarily unset mesh moving to avoid problems in meshflux
2844 // mapping. To be investigated.
2845 const bool oldMoving = mesh_.moving(false);
2846
2848 (
2849 Pstream::myProcNo(), // index of mesh to modify (== mesh_)
2850 fvMeshes,
2851 oldFaceOwner,
2852
2853 // Coupling info
2854 localBoundaryFace,
2855 remoteFaceProc,
2856 remoteBoundaryFace,
2857
2858 constructPatchMap,
2859 constructCellMap,
2860 constructFaceMap,
2861 constructPointMap
2862 );
2863
2864 mesh_.moving(oldMoving);
2865
2866
2867 if (debug)
2868 {
2869 Pout<< nl << "ADDED REMOTE MESHES:" << endl;
2870 printMeshInfo(mesh_);
2871 printFieldInfo<volScalarField>(mesh_);
2872 printFieldInfo<volVectorField>(mesh_);
2873 printFieldInfo<volSphericalTensorField>(mesh_);
2874 printFieldInfo<volSymmTensorField>(mesh_);
2875 printFieldInfo<volTensorField>(mesh_);
2876 printFieldInfo<surfaceScalarField>(mesh_);
2877 printFieldInfo<surfaceVectorField>(mesh_);
2878 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2879 printFieldInfo<surfaceSymmTensorField>(mesh_);
2880 printFieldInfo<surfaceTensorField>(mesh_);
2881 printIntFieldInfo<volScalarField::Internal>(mesh_);
2882 printIntFieldInfo<volVectorField::Internal>(mesh_);
2883 printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
2884 printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
2885 printIntFieldInfo<volTensorField::Internal>(mesh_);
2886 Pout<< nl << endl;
2887 }
2888
2889 {
2890 //- Combine sourceProc, sourcePatch, sourceFace
2891 sourceProc.setSize(mesh_.nBoundaryFaces());
2892 sourceProc = -1;
2893 sourcePatch.setSize(mesh_.nBoundaryFaces());
2894 sourcePatch = -1;
2895 sourceFace.setSize(mesh_.nBoundaryFaces());
2896 sourceFace = -1;
2897 sourceNewNbrProc.setSize(mesh_.nBoundaryFaces());
2898 sourceNewNbrProc = -1;
2899 sourcePointMaster.setSize(mesh_.nPoints());
2900 sourcePointMaster = -1;
2901
2902 if (mesh_.nPoints() > 0)
2903 {
2904 forAll(meshes, meshi)
2905 {
2906 if (domainSourceFaces.set(meshi))
2907 {
2908 const label nIntFaces =
2909 (
2910 meshi == Pstream::myProcNo()
2911 ? nOldInternalFaces
2912 : meshes[meshi].nInternalFaces()
2913 );
2914 const labelList& faceOwner
2915 (
2916 meshi == Pstream::myProcNo()
2917 ? oldFaceOwner
2918 : meshes[meshi].faceOwner()
2919 );
2920
2921 labelList& faceMap = constructFaceMap[meshi];
2922 const labelList& cellMap = constructCellMap[meshi];
2923
2924 const labelList& domainSourceFace =
2925 domainSourceFaces[meshi];
2926 const labelList& domainSourceProc =
2927 domainSourceProcs[meshi];
2928 const labelList& domainSourcePatch =
2929 domainSourcePatchs[meshi];
2930 const labelList& domainSourceNewNbr =
2931 domainSourceNewNbrProcs[meshi];
2933 (
2934 sourcePointMaster,
2935 constructPointMap[meshi]
2936 ) = domainSourcePointMasters[meshi];
2937
2938
2939 forAll(domainSourceFace, bFacei)
2940 {
2941 const label oldFacei = bFacei+nIntFaces;
2942 const label allFacei = faceMap[oldFacei];
2943 const label allbFacei = allFacei-mesh_.nInternalFaces();
2944
2945 if (allbFacei >= 0)
2946 {
2947 sourceProc[allbFacei] = domainSourceProc[bFacei];
2948 sourcePatch[allbFacei] = domainSourcePatch[bFacei];
2949 sourceFace[allbFacei] = domainSourceFace[bFacei];
2950 sourceNewNbrProc[allbFacei] =
2951 domainSourceNewNbr[bFacei];
2952 }
2953 }
2954
2955
2956 // Add flip to constructFaceMap
2957 forAll(faceMap, oldFacei)
2958 {
2959 const label allFacei = faceMap[oldFacei];
2960 const label allOwn = mesh_.faceOwner()[allFacei];
2961
2962 if (cellMap[faceOwner[oldFacei]] == allOwn)
2963 {
2964 // Master face
2965 faceMap[oldFacei] += 1;
2966 }
2967 else
2968 {
2969 // Slave face. Flip.
2970 faceMap[oldFacei] = -faceMap[oldFacei] - 1;
2971 }
2972 }
2973 }
2974 }
2975 }
2976 }
2977
2978
2979 UPstream::parRun(oldParRun); // Restore parallel state
2980
2981
2982 // Print a bit.
2983 if (debug)
2984 {
2985 Pout<< nl << "REDISTRIBUTED MESH:" << endl;
2986 printMeshInfo(mesh_);
2987 printFieldInfo<volScalarField>(mesh_);
2988 printFieldInfo<volVectorField>(mesh_);
2989 printFieldInfo<volSphericalTensorField>(mesh_);
2990 printFieldInfo<volSymmTensorField>(mesh_);
2991 printFieldInfo<volTensorField>(mesh_);
2992 printFieldInfo<surfaceScalarField>(mesh_);
2993 printFieldInfo<surfaceVectorField>(mesh_);
2994 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2995 printFieldInfo<surfaceSymmTensorField>(mesh_);
2996 printFieldInfo<surfaceTensorField>(mesh_);
2997 printIntFieldInfo<volScalarField::Internal>(mesh_);
2998 printIntFieldInfo<volVectorField::Internal>(mesh_);
2999 printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
3000 printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
3001 printIntFieldInfo<volTensorField::Internal>(mesh_);
3002 Pout<< nl << endl;
3003 }
3004
3005
3006 // See if any originally shared points need to be merged. Note: does
3007 // parallel comms. After this points and edges should again be consistent.
3008 mergeSharedPoints(sourcePointMaster, constructPointMap);
3009
3010
3011 // Add processorPatches
3012 // ~~~~~~~~~~~~~~~~~~~~
3013
3014 // Per neighbour processor, per originating patch, the patchID
3015 // For faces resulting from internal faces or normal processor patches
3016 // the originating patch is -1. For cyclics this is the cyclic patchID.
3017 List<Map<label>> procPatchID;
3018
3019 // Add processor and processorCyclic patches.
3020 addProcPatches(sourceNewNbrProc, sourcePatch, procPatchID);
3021
3022 // Put faces into correct patch. Note that we now have proper
3023 // processorPolyPatches again so repatching will take care of coupled face
3024 // ordering.
3025
3026 // Get boundary faces to be repatched. Is -1 or new patchID
3027 labelList newPatchID
3028 (
3029 getBoundaryPatch
3030 (
3031 sourceNewNbrProc,
3032 sourcePatch,
3033 procPatchID
3034 )
3035 );
3036
3037 // Change patches. Since this might change ordering of coupled faces
3038 // we also need to adapt our constructMaps.
3039 repatch(newPatchID, constructFaceMap);
3040
3041 // Bit of hack: processorFvPatchField does not get reset since created
3042 // from nothing so explicitly reset.
3043 initPatchFields<volScalarField, processorFvPatchField<scalar>>
3044 (
3045 Zero
3046 );
3047 initPatchFields<volVectorField, processorFvPatchField<vector>>
3048 (
3049 Zero
3050 );
3051 initPatchFields
3052 <
3055 >
3056 (
3057 Zero
3058 );
3059 initPatchFields<volSymmTensorField, processorFvPatchField<symmTensor>>
3060 (
3061 Zero
3062 );
3063 initPatchFields<volTensorField, processorFvPatchField<tensor>>
3064 (
3065 Zero
3066 );
3067
3068
3069 mesh_.setInstance(mesh_.time().timeName());
3070
3071
3072 // Print a bit
3073 if (debug)
3074 {
3075 Pout<< nl << "FINAL MESH:" << endl;
3076 printMeshInfo(mesh_);
3077 printFieldInfo<volScalarField>(mesh_);
3078 printFieldInfo<volVectorField>(mesh_);
3079 printFieldInfo<volSphericalTensorField>(mesh_);
3080 printFieldInfo<volSymmTensorField>(mesh_);
3081 printFieldInfo<volTensorField>(mesh_);
3082 printFieldInfo<surfaceScalarField>(mesh_);
3083 printFieldInfo<surfaceVectorField>(mesh_);
3084 printFieldInfo<surfaceSphericalTensorField>(mesh_);
3085 printFieldInfo<surfaceSymmTensorField>(mesh_);
3086 printFieldInfo<surfaceTensorField>(mesh_);
3087 printIntFieldInfo<volScalarField::Internal>(mesh_);
3088 printIntFieldInfo<volVectorField::Internal>(mesh_);
3089 printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
3090 printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
3091 printIntFieldInfo<volTensorField::Internal>(mesh_);
3092 Pout<< nl << endl;
3093 }
3094
3095 // Collect all maps and return
3097 (
3098 mesh_,
3099
3100 nOldPoints,
3101 nOldFaces,
3102 nOldCells,
3103 std::move(oldPatchStarts),
3104 std::move(oldPatchNMeshPoints),
3105
3106 std::move(subPointMap),
3107 std::move(subFaceMap),
3108 std::move(subCellMap),
3109 std::move(subPatchMap),
3110
3111 std::move(constructPointMap),
3112 std::move(constructFaceMap),
3113 std::move(constructCellMap),
3114 std::move(constructPatchMap),
3115
3116 true, // subFaceMap has flip
3117 true // constructFaceMap has flip
3118 );
3119}
3120
3121
3122// ************************************************************************* //
Various functions to operate on Lists.
bool found
label n
Info<< nl<< "Wrote faMesh in vtk format: "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.mesh().time().globalPath()/"finiteArea-edges"));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
A HashTable similar to std::unordered_map.
Definition: HashTable.H:123
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
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 transfer(List< T > &list)
Definition: List.C:447
void setSize(const label n)
Alias for resize()
Definition: List.H:218
virtual const fileName & name() const
Get the name of the stream.
Definition: OSstream.H:107
Buffers for inter-processor communications streams (UOPstream, UIPstream).
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
void finishedSends(const bool wait=true)
Mark sends as done.
void clear()
Clear individual buffers and reset states.
static void gatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
static void scatter(const List< commsStruct > &comms, T &value, const int tag, const label comm)
Broadcast data: Distribute without modification.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
const T * set(const label i) const
Definition: PtrList.H:138
A List obtained as a section of another List.
Definition: SubList.H:70
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:80
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:780
A List with indirect addressing. Like IndirectList but does not store addressing.
Definition: IndirectList.H:79
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
@ nonBlocking
"nonBlocking"
static void allToAll(const UList< int32_t > &sendData, UList< int32_t > &recvData, const label communicator=worldComm)
Exchange integer data with all processors (in the communicator).
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: UPtrList.H:71
const T * set(const label i) const
Definition: UPtrList.H:248
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
T * ptr() noexcept
Same as release().
Definition: autoPtr.H:172
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:64
A subset of mesh cells.
Definition: cellZone.H:65
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
Accumulating histogram of values. Specified bin resolution automatic generation of bins.
Definition: distribution.H:64
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:67
Sums a given list of (at least two or more) fields and outputs the result into a new field,...
Definition: add.H:161
Foam::fvBoundaryMesh.
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
static void printCoupleInfo(const primitiveMesh &, const labelList &, const labelList &, const labelList &, const labelList &)
Print some info on coupling data.
static void printMeshInfo(const fvMesh &)
Print some info on mesh.
static labelList countCells(const labelList &)
Helper function: count cells per processor in wanted distribution.
static tmp< surfaceScalarField > generateTestField(const fvMesh &)
Generate a test field on faces.
autoPtr< mapDistributePolyMesh > distribute(const labelList &dist)
Send cells to neighbours according to distribution.
static void testField(const surfaceScalarField &)
Check whether field consistent with face orientation.
Holds a reference to the original mesh (the baseMesh) and optionally to a subset of that mesh (the su...
Definition: fvMeshSubset.H:80
const labelList & faceMap() const
Return face map.
Definition: fvMeshSubsetI.H:72
const labelList & cellMap() const
Return cell map.
Definition: fvMeshSubsetI.H:91
const labelList & faceFlipMap() const
Return face map with sign to encode flipped faces.
Definition: fvMeshSubsetI.H:80
const fvMesh & subMesh() const
Return reference to subset mesh.
Definition: fvMeshSubsetI.H:48
const labelList & patchMap() const
Return patch map.
Definition: fvMeshSubsetI.H:99
const labelList & pointMap() const
Return point map.
Definition: fvMeshSubsetI.H:64
static void reorderPatches(fvMesh &, const labelList &oldToNew, const label nPatches, const bool validBoundary)
Reorder and remove trailing patches.
Definition: fvMeshTools.C:322
static label addPatch(fvMesh &mesh, const polyPatch &patch, const dictionary &patchFieldDict, const word &defaultPatchFieldType, const bool validBoundary)
Add patch. Inserts patch before all processor patches.
Definition: fvMeshTools.C:43
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:91
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:712
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:290
const surfaceVectorField & Sf() const
Return cell face area vectors.
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
virtual const word & name() const
Return name.
Definition: fvPatch.H:173
virtual label start() const
Return start label of this patch in the polyMesh face list.
Definition: fvPatch.H:179
const fvPatch & patch() const
Return patch.
Less function class that can be used for sorting processor patches.
bool operator()(const label a, const label b)
lessProcPatches(const labelList &nbrProc, const labelList &referPatchID)
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:62
const word & name() const noexcept
The patch name.
A subset of mesh points.
Definition: pointZone.H:68
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
wordList names() const
Return a list of patch names.
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order.
static void mergePoints(const polyMesh &, const Map< label > &pointToMaster, polyTopoChange &meshMod)
Helper: Merge points.
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:498
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:321
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 polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
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
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
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:380
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:364
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:315
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:79
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
const vectorField & faceCentres() const
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.
int myProcNo() const noexcept
Return processor number.
This boundary condition enables processor communication across patches.
void repatch()
Re-patch the mesh.
splitCell * master() const
Definition: splitCell.H:113
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:445
A class for managing temporary objects.
Definition: tmp.H:65
T & ref() const
Definition: tmpI.H:227
const word & name() const noexcept
The zone name.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
const polyBoundaryMesh & patches
dynamicFvMesh & mesh
engineTime & runTime
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const labelIOList & zoneID
A HashTable to objects of type <T> with a labelPair key. The hashing is based on labelPair (FixedList...
#define WarningInFunction
Report a warning using Foam::Warning.
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:108
Namespace for OpenFOAM.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:57
List< word > wordList
A List of words.
Definition: fileName.H:63
const dimensionSet dimless
Dimensionless.
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.
dimensionedScalar sign(const dimensionedScalar &ds)
List< label > labelList
A List of labels.
Definition: List.H:66
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
Definition: quaternionI.H:680
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
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
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
HashTable< label, labelPair, Foam::Hash< labelPair > > labelPairLookup
This is a Map of a labelPair to a label. Used for e.g. for face1, face2 to shared edge....
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
GeometricField< sphericalTensor, fvPatchField, volMesh > volSphericalTensorField
Definition: volFieldsFwd.H:85
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:215
errorManip< error > abort(error &err)
Definition: errorManip.H:144
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
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.
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
dimensionedScalar cos(const dimensionedScalar &ds)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
label newPointi
Definition: readKivaGrid.H:496
dictionary dict
volScalarField & b
Definition: createFields.H:27
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
static const char *const typeName
The type name used in ensight case files.
Foam::surfaceFields.