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-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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"
31 #include "fvMeshAdder.H"
32 #include "faceCoupleInfo.H"
33 #include "processorFvPatchField.H"
34 #include "processorFvsPatchField.H"
37 #include "polyTopoChange.H"
38 #include "removeCells.H"
39 #include "polyModifyFace.H"
40 #include "polyRemovePoint.H"
41 #include "mapDistributePolyMesh.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 
54 namespace Foam
55 {
56  defineTypeNameAndDebug(fvMeshDistribute, 0);
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 
94 void 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 
168 Foam::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 
199 Foam::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 
234  const fvBoundaryMesh& patches = mesh.boundary();
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 
311 Foam::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  (
415  IOobject
416  (
417  "myFlux",
418  mesh.time().timeName(),
419  mesh,
422  ),
423  mesh,
425  )
426  );
427  surfaceScalarField& fld = tfld.ref();
428 
429  const surfaceVectorField n(mesh.Sf()/mesh.magSf());
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 
461  const surfaceVectorField n(mesh.Sf()/mesh.magSf());
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 
510 Foam::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 
578 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
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  autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
643  mapPolyMesh& map = *mapPtr;
644 
645  // Update fields. No inflation, parallel sync.
646  mesh_.updateMesh(map);
647 
648  // Map patch fields using stored boundary fields. Note: assumes order
649  // of fields has not changed in object registry!
650  mapBoundaryFields<scalar, surfaceMesh>(map, sFlds);
651  mapBoundaryFields<vector, surfaceMesh>(map, vFlds);
652  mapBoundaryFields<sphericalTensor, surfaceMesh>(map, sptFlds);
653  mapBoundaryFields<symmTensor, surfaceMesh>(map, sytFlds);
654  mapBoundaryFields<tensor, surfaceMesh>(map, tFlds);
655 
656 
657  // Move mesh (since morphing does not do this)
658  if (map.hasMotionPoints())
659  {
660  mesh_.movePoints(map.preMotionPoints());
661  }
662 
663  // Adapt constructMaps.
664 
665  if (debug)
666  {
667  label index = map.reverseFaceMap().find(-1);
668 
669  if (index != -1)
670  {
672  << "reverseFaceMap contains -1 at index:"
673  << index << endl
674  << "This means that the repatch operation was not just"
675  << " a shuffle?" << abort(FatalError);
676  }
677  }
678 
679  forAll(constructFaceMap, proci)
680  {
681  inplaceRenumberWithFlip
682  (
683  map.reverseFaceMap(),
684  false,
685  true,
686  constructFaceMap[proci]
687  );
688  }
689 
690  return mapPtr;
691 }
692 
693 
694 // Detect shared points. Need processor patches to be present.
695 // Background: when adding bits of mesh one can get points which
696 // share the same position but are only detectable to be topologically
697 // the same point when doing parallel analysis. This routine will
698 // merge those points.
699 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
700 (
701  const labelList& pointToGlobalMaster,
702  labelListList& constructPointMap
703 )
704 {
705  // Find out which sets of points get merged and create a map from
706  // mesh point to unique point.
707 
708  label nShared = 0;
709  forAll(pointToGlobalMaster, pointi)
710  {
711  if (pointToGlobalMaster[pointi] != -1)
712  {
713  nShared++;
714  }
715  }
716 
717  if (debug)
718  {
719  Pout<< "mergeSharedPoints : found " << nShared
720  << " points on processor boundaries" << nl << endl;
721  }
722 
723  Map<label> globalMasterToLocalMaster(2*nShared);
724  Map<label> pointToMaster(2*nShared);
725  label nMatch = 0;
726 
727  forAll(pointToGlobalMaster, pointi)
728  {
729  label globali = pointToGlobalMaster[pointi];
730  if (globali != -1)
731  {
732  const auto iter = globalMasterToLocalMaster.cfind(globali);
733 
734  if (iter.found())
735  {
736  // Matched to existing master
737  pointToMaster.insert(pointi, *iter);
738  nMatch++;
739  }
740  else
741  {
742  // Found first point. Designate as master
743  globalMasterToLocalMaster.insert(globali, pointi);
744  pointToMaster.insert(pointi, pointi);
745  }
746  }
747  }
748 
749  reduce(nMatch, sumOp<label>());
750 
751  if (debug)
752  {
753  Pout<< "mergeSharedPoints : found "
754  << nMatch << " mergeable points" << nl << endl;
755  }
756 
757 
758  if (nMatch == 0)
759  {
760  return nullptr;
761  }
762 
763 
764  polyTopoChange meshMod(mesh_);
765 
766  fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
767 
768  // Change the mesh (no inflation). Note: parallel comms allowed.
769  autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
770  mapPolyMesh& map = *mapPtr;
771 
772  // Update fields. No inflation, parallel sync.
773  mesh_.updateMesh(map);
774 
775  // Adapt constructMaps for merged points.
776  forAll(constructPointMap, proci)
777  {
778  labelList& constructMap = constructPointMap[proci];
779 
780  forAll(constructMap, i)
781  {
782  label oldPointi = constructMap[i];
783 
784  label newPointi = map.reversePointMap()[oldPointi];
785 
786  if (newPointi < -1)
787  {
788  constructMap[i] = -newPointi-2;
789  }
790  else if (newPointi >= 0)
791  {
792  constructMap[i] = newPointi;
793  }
794  else
795  {
797  << "Problem. oldPointi:" << oldPointi
798  << " newPointi:" << newPointi << abort(FatalError);
799  }
800  }
801  }
802 
803  return mapPtr;
804 }
805 
806 
807 void Foam::fvMeshDistribute::getCouplingData
808 (
809  const labelList& distribution,
810  labelList& sourceFace,
811  labelList& sourceProc,
812  labelList& sourcePatch,
813  labelList& sourceNewNbrProc,
814  labelList& sourcePointMaster
815 ) const
816 {
817  // Construct the coupling information for all (boundary) faces and
818  // points
819 
820  const label nBnd = mesh_.nBoundaryFaces();
821  sourceFace.setSize(nBnd);
822  sourceProc.setSize(nBnd);
823  sourcePatch.setSize(nBnd);
824  sourceNewNbrProc.setSize(nBnd);
825 
826  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
827 
828  // Get neighbouring meshFace labels and new processor of coupled boundaries.
829  labelList nbrFaces(nBnd, -1);
830  labelList nbrNewNbrProc(nBnd, -1);
831 
832  forAll(patches, patchi)
833  {
834  const polyPatch& pp = patches[patchi];
835 
836  if (pp.coupled())
837  {
838  label offset = pp.start() - mesh_.nInternalFaces();
839 
840  // Mesh labels of faces on this side
841  forAll(pp, i)
842  {
843  label bndI = offset + i;
844  nbrFaces[bndI] = pp.start()+i;
845  }
846 
847  // Which processor they will end up on
848  SubList<label>(nbrNewNbrProc, pp.size(), offset) =
849  labelUIndList(distribution, pp.faceCells())();
850  }
851  }
852 
853 
854  // Exchange the boundary data
855  syncTools::swapBoundaryFaceList(mesh_, nbrFaces);
856  syncTools::swapBoundaryFaceList(mesh_, nbrNewNbrProc);
857 
858 
859  forAll(patches, patchi)
860  {
861  const polyPatch& pp = patches[patchi];
862  label offset = pp.start() - mesh_.nInternalFaces();
863 
864  if (isA<processorPolyPatch>(pp))
865  {
866  const processorPolyPatch& procPatch =
867  refCast<const processorPolyPatch>(pp);
868 
869  // Check which of the two faces we store.
870 
871  if (procPatch.owner())
872  {
873  // Use my local face labels
874  forAll(pp, i)
875  {
876  label bndI = offset + i;
877  sourceFace[bndI] = pp.start()+i;
878  sourceProc[bndI] = Pstream::myProcNo();
879  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
880  }
881  }
882  else
883  {
884  // Use my neighbours face labels
885  forAll(pp, i)
886  {
887  label bndI = offset + i;
888  sourceFace[bndI] = nbrFaces[bndI];
889  sourceProc[bndI] = procPatch.neighbProcNo();
890  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
891  }
892  }
893 
894 
895  label patchi = -1;
896  if (isA<processorCyclicPolyPatch>(pp))
897  {
898  patchi = refCast<const processorCyclicPolyPatch>
899  (
900  pp
901  ).referPatchID();
902  }
903 
904  forAll(pp, i)
905  {
906  label bndI = offset + i;
907  sourcePatch[bndI] = patchi;
908  }
909  }
910  else if (isA<cyclicPolyPatch>(pp))
911  {
912  const cyclicPolyPatch& cpp = refCast<const cyclicPolyPatch>(pp);
913 
914  if (cpp.owner())
915  {
916  forAll(pp, i)
917  {
918  label bndI = offset + i;
919  sourceFace[bndI] = pp.start()+i;
920  sourceProc[bndI] = Pstream::myProcNo();
921  sourcePatch[bndI] = patchi;
922  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
923  }
924  }
925  else
926  {
927  forAll(pp, i)
928  {
929  label bndI = offset + i;
930  sourceFace[bndI] = nbrFaces[bndI];
931  sourceProc[bndI] = Pstream::myProcNo();
932  sourcePatch[bndI] = patchi;
933  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
934  }
935  }
936  }
937  else
938  {
939  // Normal (physical) boundary
940  forAll(pp, i)
941  {
942  label bndI = offset + i;
943  sourceFace[bndI] = -1;
944  sourceProc[bndI] = -1;
945  sourcePatch[bndI] = patchi;
946  sourceNewNbrProc[bndI] = -1;
947  }
948  }
949  }
950 
951 
952  // Collect coupled (collocated) points
953  sourcePointMaster.setSize(mesh_.nPoints());
954  sourcePointMaster = -1;
955  {
956  // Assign global master point
957  const globalIndex globalPoints(mesh_.nPoints());
958 
959  const globalMeshData& gmd = mesh_.globalData();
960  const indirectPrimitivePatch& cpp = gmd.coupledPatch();
961  const labelList& meshPoints = cpp.meshPoints();
962  const mapDistribute& slavesMap = gmd.globalCoPointSlavesMap();
963  const labelListList& slaves = gmd.globalCoPointSlaves();
964 
965  labelList elems(slavesMap.constructSize(), -1);
966  forAll(meshPoints, pointi)
967  {
968  const labelList& slots = slaves[pointi];
969 
970  if (slots.size())
971  {
972  // pointi is a master. Assign a unique label.
973 
974  label globalPointi = globalPoints.toGlobal(meshPoints[pointi]);
975  elems[pointi] = globalPointi;
976  forAll(slots, i)
977  {
978  label sloti = slots[i];
979  if (sloti >= meshPoints.size())
980  {
981  // Filter out local collocated points. We don't want
982  // to merge these
983  elems[slots[i]] = globalPointi;
984  }
985  }
986  }
987  }
988 
989  // Push slave-slot data back to slaves
990  slavesMap.reverseDistribute(elems.size(), elems, false);
991 
992  // Extract back onto mesh
993  forAll(meshPoints, pointi)
994  {
995  sourcePointMaster[meshPoints[pointi]] = elems[pointi];
996  }
997  }
998 }
999 
1000 
1001 // Subset the neighbourCell/neighbourProc fields
1002 void Foam::fvMeshDistribute::subsetCouplingData
1003 (
1004  const fvMesh& mesh,
1005  const labelList& pointMap,
1006  const labelList& faceMap,
1007  const labelList& cellMap,
1008 
1009  const labelList& oldDistribution,
1010  const labelList& oldFaceOwner,
1011  const labelList& oldFaceNeighbour,
1012  const label oldInternalFaces,
1013 
1014  const labelList& sourceFace,
1015  const labelList& sourceProc,
1016  const labelList& sourcePatch,
1017  const labelList& sourceNewNbrProc,
1018  const labelList& sourcePointMaster,
1019 
1020  labelList& subFace,
1021  labelList& subProc,
1022  labelList& subPatch,
1023  labelList& subNewNbrProc,
1024  labelList& subPointMaster
1025 )
1026 {
1027  subFace.setSize(mesh.nBoundaryFaces());
1028  subProc.setSize(mesh.nBoundaryFaces());
1029  subPatch.setSize(mesh.nBoundaryFaces());
1030  subNewNbrProc.setSize(mesh.nBoundaryFaces());
1031 
1032  forAll(subFace, newBFacei)
1033  {
1034  label newFacei = newBFacei + mesh.nInternalFaces();
1035 
1036  label oldFacei = faceMap[newFacei];
1037 
1038  // Was oldFacei internal face? If so which side did we get.
1039  if (oldFacei < oldInternalFaces)
1040  {
1041  subFace[newBFacei] = oldFacei;
1042  subProc[newBFacei] = Pstream::myProcNo();
1043  subPatch[newBFacei] = -1;
1044 
1045  label oldOwn = oldFaceOwner[oldFacei];
1046  label oldNei = oldFaceNeighbour[oldFacei];
1047 
1048  if (oldOwn == cellMap[mesh.faceOwner()[newFacei]])
1049  {
1050  // We kept the owner side. Where does the neighbour move to?
1051  subNewNbrProc[newBFacei] = oldDistribution[oldNei];
1052  }
1053  else
1054  {
1055  // We kept the neighbour side.
1056  subNewNbrProc[newBFacei] = oldDistribution[oldOwn];
1057  }
1058  }
1059  else
1060  {
1061  // Was boundary face. Take over boundary information
1062  label oldBFacei = oldFacei - oldInternalFaces;
1063 
1064  subFace[newBFacei] = sourceFace[oldBFacei];
1065  subProc[newBFacei] = sourceProc[oldBFacei];
1066  subPatch[newBFacei] = sourcePatch[oldBFacei];
1067  subNewNbrProc[newBFacei] = sourceNewNbrProc[oldBFacei];
1068  }
1069  }
1070 
1071 
1072  subPointMaster = UIndirectList<label>(sourcePointMaster, pointMap);
1073 }
1074 
1075 
1076 // Find cells on mesh whose faceID/procID match the neighbour cell/proc of
1077 // domainMesh. Store the matching face.
1078 void Foam::fvMeshDistribute::findCouples
1079 (
1080  const primitiveMesh& mesh,
1081  const labelList& sourceFace,
1082  const labelList& sourceProc,
1083  const labelList& sourcePatch,
1084 
1085  const label domain,
1086  const primitiveMesh& domainMesh,
1087  const labelList& domainFace,
1088  const labelList& domainProc,
1089  const labelList& domainPatch,
1090 
1091  labelList& masterCoupledFaces,
1092  labelList& slaveCoupledFaces
1093 )
1094 {
1095  // Store domain neighbour as map so we can easily look for pair
1096  // with same face+proc.
1097  labelPairLookup map(domainFace.size());
1098 
1099  forAll(domainProc, bFacei)
1100  {
1101  if (domainProc[bFacei] != -1 && domainPatch[bFacei] == -1)
1102  {
1103  map.insert
1104  (
1105  labelPair(domainFace[bFacei], domainProc[bFacei]),
1106  bFacei
1107  );
1108  }
1109  }
1110 
1111 
1112  // Try to match mesh data.
1113 
1114  masterCoupledFaces.setSize(domainFace.size());
1115  slaveCoupledFaces.setSize(domainFace.size());
1116  label coupledI = 0;
1117 
1118  forAll(sourceFace, bFacei)
1119  {
1120  if (sourceProc[bFacei] != -1 && sourcePatch[bFacei] == -1)
1121  {
1122  labelPair myData(sourceFace[bFacei], sourceProc[bFacei]);
1123 
1124  const auto iter = map.cfind(myData);
1125 
1126  if (iter.found())
1127  {
1128  label nbrBFacei = *iter;
1129 
1130  masterCoupledFaces[coupledI] = mesh.nInternalFaces() + bFacei;
1131  slaveCoupledFaces[coupledI] =
1132  domainMesh.nInternalFaces()
1133  + nbrBFacei;
1134 
1135  coupledI++;
1136  }
1137  }
1138  }
1139 
1140  masterCoupledFaces.setSize(coupledI);
1141  slaveCoupledFaces.setSize(coupledI);
1142 
1143  if (debug)
1144  {
1145  Pout<< "findCouples : found " << coupledI
1146  << " faces that will be stitched" << nl << endl;
1147  }
1148 }
1149 
1150 
1151 void Foam::fvMeshDistribute::findCouples
1152 (
1153  const UPtrList<polyMesh>& meshes,
1154  const PtrList<labelList>& domainSourceFaces,
1155  const PtrList<labelList>& domainSourceProcs,
1156  const PtrList<labelList>& domainSourcePatchs,
1157 
1158  labelListList& localBoundaryFace,
1159  labelListList& remoteFaceProc,
1160  labelListList& remoteBoundaryFace
1161 )
1162 {
1163  // Collect all matching processor face pairs. These are all the
1164  // faces for which we have both sides
1165 
1166  // Pass 0: count number of inter-processor faces
1167  labelList nProcFaces(meshes.size(), 0);
1168  forAll(meshes, meshi)
1169  {
1170  if (meshes.set(meshi))
1171  {
1172  const labelList& domainProc = domainSourceProcs[meshi];
1173  const labelList& domainPatch = domainSourcePatchs[meshi];
1174 
1175  forAll(domainProc, bFacei)
1176  {
1177  if (domainProc[bFacei] != -1 && domainPatch[bFacei] == -1)
1178  {
1179  nProcFaces[meshi]++;
1180  }
1181  }
1182  }
1183  }
1184 
1185  if (debug)
1186  {
1187  Pout<< "fvMeshDistribute::findCouples : nProcFaces:"
1188  << flatOutput(nProcFaces) << endl;
1189  }
1190 
1191 
1192  // Size
1193  List<DynamicList<label>> dynLocalFace(Pstream::nProcs());
1194  List<DynamicList<label>> dynRemoteProc(Pstream::nProcs());
1195  List<DynamicList<label>> dynRemoteFace(Pstream::nProcs());
1196 
1197  forAll(meshes, meshi)
1198  {
1199  if (meshes.set(meshi))
1200  {
1201  dynLocalFace[meshi].setCapacity(nProcFaces[meshi]);
1202  dynRemoteProc[meshi].setCapacity(nProcFaces[meshi]);
1203  dynRemoteFace[meshi].setCapacity(nProcFaces[meshi]);
1204  }
1205  }
1206 
1207 
1208  // Insert all into big map. Find matches
1209  LabelPairMap<labelPair> map(2*sum(nProcFaces));
1210 
1211  nProcFaces = 0;
1212 
1213  forAll(meshes, meshi)
1214  {
1215  if (meshes.set(meshi))
1216  {
1217  const labelList& domainFace = domainSourceFaces[meshi];
1218  const labelList& domainProc = domainSourceProcs[meshi];
1219  const labelList& domainPatch = domainSourcePatchs[meshi];
1220 
1221  forAll(domainProc, bFacei)
1222  {
1223  if (domainProc[bFacei] != -1 && domainPatch[bFacei] == -1)
1224  {
1225  const labelPair key
1226  (
1227  domainProc[bFacei],
1228  domainFace[bFacei]
1229  );
1230  auto fnd = map.find(key);
1231 
1232  if (!fnd.found())
1233  {
1234  // Insert
1235  map.emplace(key, meshi, bFacei);
1236  }
1237  else
1238  {
1239  // Second occurence. Found match.
1240  const label matchProci = fnd().first();
1241  const label matchFacei = fnd().second();
1242 
1243  dynLocalFace[meshi].append(bFacei);
1244  dynRemoteProc[meshi].append(matchProci);
1245  dynRemoteFace[meshi].append(matchFacei);
1246  nProcFaces[meshi]++;
1247 
1248  dynLocalFace[matchProci].append(matchFacei);
1249  dynRemoteProc[matchProci].append(meshi);
1250  dynRemoteFace[matchProci].append(bFacei);
1251  nProcFaces[matchProci]++;
1252  }
1253  }
1254  }
1255  }
1256  }
1257 
1258  if (debug)
1259  {
1260  Pout<< "fvMeshDistribute::findCouples : stored procFaces:"
1261  << map.size() << endl;
1262  }
1263 
1264  localBoundaryFace.setSize(Pstream::nProcs());
1265  remoteFaceProc.setSize(Pstream::nProcs());
1266  remoteBoundaryFace.setSize(Pstream::nProcs());
1267  forAll(meshes, meshi)
1268  {
1269  if (meshes.set(meshi))
1270  {
1271  localBoundaryFace[meshi] = std::move(dynLocalFace[meshi]);
1272  remoteFaceProc[meshi] = std::move(dynRemoteProc[meshi]);
1273  remoteBoundaryFace[meshi] = std::move(dynRemoteFace[meshi]);
1274  }
1275  }
1276 
1277 
1278  if (debug)
1279  {
1280  Pout<< "fvMeshDistribute::findCouples : found matches:"
1281  << flatOutput(nProcFaces) << endl;
1282  }
1283 }
1284 
1285 
1286 // Map data on boundary faces to new mesh (resulting from adding two meshes)
1287 Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
1288 (
1289  const primitiveMesh& mesh, // mesh after adding
1290  const mapAddedPolyMesh& map,
1291  const labelList& boundaryData0, // on mesh before adding
1292  const label nInternalFaces1,
1293  const labelList& boundaryData1 // on added mesh
1294 )
1295 {
1296  labelList newBoundaryData(mesh.nBoundaryFaces());
1297 
1298  forAll(boundaryData0, oldBFacei)
1299  {
1300  label newFacei = map.oldFaceMap()[oldBFacei + map.nOldInternalFaces()];
1301 
1302  // Face still exists (is necessary?) and still boundary face
1303  if (newFacei >= 0 && newFacei >= mesh.nInternalFaces())
1304  {
1305  newBoundaryData[newFacei - mesh.nInternalFaces()] =
1306  boundaryData0[oldBFacei];
1307  }
1308  }
1309 
1310  forAll(boundaryData1, addedBFacei)
1311  {
1312  label newFacei = map.addedFaceMap()[addedBFacei + nInternalFaces1];
1313 
1314  if (newFacei >= 0 && newFacei >= mesh.nInternalFaces())
1315  {
1316  newBoundaryData[newFacei - mesh.nInternalFaces()] =
1317  boundaryData1[addedBFacei];
1318  }
1319  }
1320 
1321  return newBoundaryData;
1322 }
1323 
1324 
1325 Foam::labelList Foam::fvMeshDistribute::mapPointData
1326 (
1327  const primitiveMesh& mesh, // mesh after adding
1328  const mapAddedPolyMesh& map,
1329  const labelList& boundaryData0, // on mesh before adding
1330  const labelList& boundaryData1 // on added mesh
1331 )
1332 {
1333  labelList newBoundaryData(mesh.nPoints());
1334 
1335  forAll(boundaryData0, oldPointi)
1336  {
1337  label newPointi = map.oldPointMap()[oldPointi];
1338 
1339  // Point still exists (is necessary?)
1340  if (newPointi >= 0)
1341  {
1342  newBoundaryData[newPointi] = boundaryData0[oldPointi];
1343  }
1344  }
1345 
1346  forAll(boundaryData1, addedPointi)
1347  {
1348  label newPointi = map.addedPointMap()[addedPointi];
1349 
1350  if (newPointi >= 0)
1351  {
1352  newBoundaryData[newPointi] = boundaryData1[addedPointi];
1353  }
1354  }
1355 
1356  return newBoundaryData;
1357 }
1358 
1359 
1360 // Remove cells. Add all exposed faces to patch oldInternalPatchi
1361 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
1362 (
1363  const labelList& cellsToRemove,
1364  const label oldInternalPatchi
1365 )
1366 {
1367  // Mesh change engine
1368  polyTopoChange meshMod(mesh_);
1369 
1370  // Cell removal topo engine. Do NOT synchronize parallel since
1371  // we are doing a local cell removal.
1372  removeCells cellRemover(mesh_, false);
1373 
1374  // Get all exposed faces
1375  labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
1376 
1377  // Insert the topo changes
1378  cellRemover.setRefinement
1379  (
1380  cellsToRemove,
1381  exposedFaces,
1382  labelList(exposedFaces.size(), oldInternalPatchi), // patch for exposed
1383  // faces.
1384  meshMod
1385  );
1386 
1387 
1389  //tmp<surfaceScalarField> sfld(generateTestField(mesh_));
1390 
1391  // Save internal fields (note: not as DimensionedFields since would
1392  // get mapped)
1393  PtrList<Field<scalar>> sFlds;
1394  saveInternalFields(sFlds);
1395  PtrList<Field<vector>> vFlds;
1396  saveInternalFields(vFlds);
1397  PtrList<Field<sphericalTensor>> sptFlds;
1398  saveInternalFields(sptFlds);
1399  PtrList<Field<symmTensor>> sytFlds;
1400  saveInternalFields(sytFlds);
1401  PtrList<Field<tensor>> tFlds;
1402  saveInternalFields(tFlds);
1403 
1404  // Change the mesh. No inflation. Note: no parallel comms allowed.
1405  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
1406 
1407  // Update fields
1408  mesh_.updateMesh(map());
1409 
1410 
1411  // Any exposed faces in a surfaceField will not be mapped. Map the value
1412  // of these separately (until there is support in all PatchFields for
1413  // mapping from internal faces ...)
1414 
1415  mapExposedFaces(map(), sFlds);
1416  mapExposedFaces(map(), vFlds);
1417  mapExposedFaces(map(), sptFlds);
1418  mapExposedFaces(map(), sytFlds);
1419  mapExposedFaces(map(), tFlds);
1420 
1421 
1423  //testField(sfld);
1424 
1425 
1426  // Move mesh (since morphing does not do this)
1427  if (map().hasMotionPoints())
1428  {
1429  mesh_.movePoints(map().preMotionPoints());
1430  }
1431 
1432 
1433  return map;
1434 }
1435 
1436 
1437 // Delete and add processor patches. Changes mesh and returns per neighbour proc
1438 // the processor patchID.
1439 void Foam::fvMeshDistribute::addProcPatches
1440 (
1441  const labelList& nbrProc, // processor that neighbour is now on
1442  const labelList& referPatchID, // patchID (or -1) I originated from
1443  List<Map<label>>& procPatchID
1444 )
1445 {
1446  // Now use the neighbourFace/Proc to repatch the mesh. These lists
1447  // contain for all current boundary faces the global patchID (for non-proc
1448  // patch) or the processor.
1449 
1450  // Determine a visit order such that the processor patches get added
1451  // in order of increasing neighbour processor (and for same neighbour
1452  // processor (in case of processor cyclics) in order of increasing
1453  // 'refer' patch)
1454  labelList indices;
1455  sortedOrder(nbrProc, indices, lessProcPatches(nbrProc, referPatchID));
1456 
1457  procPatchID.setSize(Pstream::nProcs());
1458 
1459  forAll(indices, i)
1460  {
1461  label bFacei = indices[i];
1462  label proci = nbrProc[bFacei];
1463 
1464  if (proci != -1 && proci != Pstream::myProcNo())
1465  {
1466  if (!procPatchID[proci].found(referPatchID[bFacei]))
1467  {
1468  // No patch for neighbour yet. Is either a normal processor
1469  // patch or a processorCyclic patch.
1470 
1471  if (referPatchID[bFacei] == -1)
1472  {
1473  // Ordinary processor boundary
1474 
1475  processorPolyPatch pp
1476  (
1477  0, // size
1478  mesh_.nFaces(),
1479  mesh_.boundaryMesh().size(),
1480  mesh_.boundaryMesh(),
1482  proci
1483  );
1484 
1485  procPatchID[proci].insert
1486  (
1487  referPatchID[bFacei],
1489  (
1490  mesh_,
1491  pp,
1492  dictionary(), // optional per field patchField
1493  processorFvPatchField<scalar>::typeName,
1494  false // not parallel sync
1495  )
1496  );
1497  }
1498  else
1499  {
1500  const coupledPolyPatch& pcPatch
1501  = refCast<const coupledPolyPatch>
1502  (
1503  mesh_.boundaryMesh()[referPatchID[bFacei]]
1504  );
1505  processorCyclicPolyPatch pp
1506  (
1507  0, // size
1508  mesh_.nFaces(),
1509  mesh_.boundaryMesh().size(),
1510  mesh_.boundaryMesh(),
1512  proci,
1513  pcPatch.name(),
1514  pcPatch.transform()
1515  );
1516 
1517  procPatchID[proci].insert
1518  (
1519  referPatchID[bFacei],
1521  (
1522  mesh_,
1523  pp,
1524  dictionary(), // optional per field patchField
1525  processorCyclicFvPatchField<scalar>::typeName,
1526  false // not parallel sync
1527  )
1528  );
1529  }
1530  }
1531  }
1532  }
1533 }
1534 
1535 
1536 // Get boundary faces to be repatched. Is -1 or new patchID
1537 Foam::labelList Foam::fvMeshDistribute::getBoundaryPatch
1538 (
1539  const labelList& nbrProc, // new processor per boundary face
1540  const labelList& referPatchID, // patchID (or -1) I originated from
1541  const List<Map<label>>& procPatchID // per proc the new procPatches
1542 )
1543 {
1544  labelList patchIDs(nbrProc);
1545 
1546  forAll(nbrProc, bFacei)
1547  {
1548  if (nbrProc[bFacei] == Pstream::myProcNo())
1549  {
1550  label origPatchi = referPatchID[bFacei];
1551  patchIDs[bFacei] = origPatchi;
1552  }
1553  else if (nbrProc[bFacei] != -1)
1554  {
1555  label origPatchi = referPatchID[bFacei];
1556  patchIDs[bFacei] = procPatchID[nbrProc[bFacei]][origPatchi];
1557  }
1558  else
1559  {
1560  patchIDs[bFacei] = -1;
1561  }
1562  }
1563  return patchIDs;
1564 }
1565 
1566 
1567 // Send mesh and coupling data.
1568 void Foam::fvMeshDistribute::sendMesh
1569 (
1570  const label domain,
1571  const fvMesh& mesh,
1572 
1573  const wordList& pointZoneNames,
1574  const wordList& faceZoneNames,
1575  const wordList& cellZoneNames,
1576 
1577  const labelList& sourceFace,
1578  const labelList& sourceProc,
1579  const labelList& sourcePatch,
1580  const labelList& sourceNewNbrProc,
1581  const labelList& sourcePointMaster,
1582  Ostream& toDomain
1583 )
1584 {
1585  if (debug)
1586  {
1587  Pout<< "Sending to domain " << domain << nl
1588  << " nPoints:" << mesh.nPoints() << nl
1589  << " nFaces:" << mesh.nFaces() << nl
1590  << " nCells:" << mesh.nCells() << nl
1591  << " nPatches:" << mesh.boundaryMesh().size() << nl
1592  << endl;
1593  }
1594 
1595  // Assume sparse, possibly overlapping point zones. Get contents
1596  // in merged-zone indices.
1597  CompactListList<label> zonePoints;
1598  {
1599  const pointZoneMesh& pointZones = mesh.pointZones();
1600 
1601  labelList rowSizes(pointZoneNames.size(), Zero);
1602 
1603  forAll(pointZoneNames, nameI)
1604  {
1605  label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1606 
1607  if (myZoneID != -1)
1608  {
1609  rowSizes[nameI] = pointZones[myZoneID].size();
1610  }
1611  }
1612  zonePoints.setSize(rowSizes);
1613 
1614  forAll(pointZoneNames, nameI)
1615  {
1616  label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1617 
1618  if (myZoneID != -1)
1619  {
1620  zonePoints[nameI].deepCopy(pointZones[myZoneID]);
1621  }
1622  }
1623  }
1624 
1625  // Assume sparse, possibly overlapping face zones
1626  CompactListList<label> zoneFaces;
1627  CompactListList<bool> zoneFaceFlip;
1628  {
1629  const faceZoneMesh& faceZones = mesh.faceZones();
1630 
1631  labelList rowSizes(faceZoneNames.size(), Zero);
1632 
1633  forAll(faceZoneNames, nameI)
1634  {
1635  label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1636 
1637  if (myZoneID != -1)
1638  {
1639  rowSizes[nameI] = faceZones[myZoneID].size();
1640  }
1641  }
1642 
1643  zoneFaces.setSize(rowSizes);
1644  zoneFaceFlip.setSize(rowSizes);
1645 
1646  forAll(faceZoneNames, nameI)
1647  {
1648  label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1649 
1650  if (myZoneID != -1)
1651  {
1652  zoneFaces[nameI].deepCopy(faceZones[myZoneID]);
1653  zoneFaceFlip[nameI].deepCopy(faceZones[myZoneID].flipMap());
1654  }
1655  }
1656  }
1657 
1658  // Assume sparse, possibly overlapping cell zones
1659  CompactListList<label> zoneCells;
1660  {
1661  const cellZoneMesh& cellZones = mesh.cellZones();
1662 
1663  labelList rowSizes(cellZoneNames.size(), Zero);
1664 
1665  forAll(cellZoneNames, nameI)
1666  {
1667  label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1668 
1669  if (myZoneID != -1)
1670  {
1671  rowSizes[nameI] = cellZones[myZoneID].size();
1672  }
1673  }
1674 
1675  zoneCells.setSize(rowSizes);
1676 
1677  forAll(cellZoneNames, nameI)
1678  {
1679  label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1680 
1681  if (myZoneID != -1)
1682  {
1683  zoneCells[nameI].deepCopy(cellZones[myZoneID]);
1684  }
1685  }
1686  }
1688  //labelList cellZoneID;
1689  //if (hasCellZones)
1690  //{
1691  // cellZoneID.setSize(mesh.nCells());
1692  // cellZoneID = -1;
1693  //
1694  // const cellZoneMesh& cellZones = mesh.cellZones();
1695  //
1696  // forAll(cellZones, zoneI)
1697  // {
1698  // labelUIndList(cellZoneID, cellZones[zoneI]) = zoneI;
1699  // }
1700  //}
1701 
1702  // Send
1703  toDomain
1704  << mesh.points()
1705  << CompactListList<label, face>(mesh.faces())
1706  << mesh.faceOwner()
1707  << mesh.faceNeighbour()
1708  << mesh.boundaryMesh()
1709 
1710  << zonePoints
1711  << zoneFaces
1712  << zoneFaceFlip
1713  << zoneCells
1714 
1715  << sourceFace
1716  << sourceProc
1717  << sourcePatch
1718  << sourceNewNbrProc
1719  << sourcePointMaster;
1720 
1721 
1722  if (debug)
1723  {
1724  Pout<< "Started sending mesh to domain " << domain
1725  << endl;
1726  }
1727 }
1728 
1729 
1730 // Receive mesh. Opposite of sendMesh
1731 Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
1732 (
1733  const label domain,
1734  const wordList& pointZoneNames,
1735  const wordList& faceZoneNames,
1736  const wordList& cellZoneNames,
1737  const Time& runTime,
1738  labelList& domainSourceFace,
1739  labelList& domainSourceProc,
1740  labelList& domainSourcePatch,
1741  labelList& domainSourceNewNbrProc,
1742  labelList& domainSourcePointMaster,
1743  Istream& fromNbr
1744 )
1745 {
1746  pointField domainPoints(fromNbr);
1747  faceList domainFaces = CompactListList<label, face>(fromNbr)();
1748  labelList domainAllOwner(fromNbr);
1749  labelList domainAllNeighbour(fromNbr);
1750  PtrList<entry> patchEntries(fromNbr);
1751 
1752  CompactListList<label> zonePoints(fromNbr);
1753  CompactListList<label> zoneFaces(fromNbr);
1754  CompactListList<bool> zoneFaceFlip(fromNbr);
1755  CompactListList<label> zoneCells(fromNbr);
1756 
1757  fromNbr
1758  >> domainSourceFace
1759  >> domainSourceProc
1760  >> domainSourcePatch
1761  >> domainSourceNewNbrProc
1762  >> domainSourcePointMaster;
1763 
1764  // Construct fvMesh
1765  auto domainMeshPtr = autoPtr<fvMesh>::New
1766  (
1767  IOobject
1768  (
1770  runTime.timeName(),
1771  runTime,
1773  ),
1774  std::move(domainPoints),
1775  std::move(domainFaces),
1776  std::move(domainAllOwner),
1777  std::move(domainAllNeighbour),
1778  false // no parallel comms
1779  );
1780  fvMesh& domainMesh = *domainMeshPtr;
1781 
1782  List<polyPatch*> patches(patchEntries.size());
1783 
1784  forAll(patchEntries, patchi)
1785  {
1786  patches[patchi] = polyPatch::New
1787  (
1788  patchEntries[patchi].keyword(),
1789  patchEntries[patchi].dict(),
1790  patchi,
1791  domainMesh.boundaryMesh()
1792  ).ptr();
1793  }
1794  // Add patches; no parallel comms
1795  domainMesh.addFvPatches(patches, false);
1796 
1797  // Construct zones
1798  List<pointZone*> pZonePtrs(pointZoneNames.size());
1799  forAll(pZonePtrs, i)
1800  {
1801  pZonePtrs[i] = new pointZone
1802  (
1803  pointZoneNames[i],
1804  zonePoints[i],
1805  i,
1806  domainMesh.pointZones()
1807  );
1808  }
1809 
1810  List<faceZone*> fZonePtrs(faceZoneNames.size());
1811  forAll(fZonePtrs, i)
1812  {
1813  fZonePtrs[i] = new faceZone
1814  (
1815  faceZoneNames[i],
1816  zoneFaces[i],
1817  zoneFaceFlip[i],
1818  i,
1819  domainMesh.faceZones()
1820  );
1821  }
1822 
1823  List<cellZone*> cZonePtrs(cellZoneNames.size());
1824  forAll(cZonePtrs, i)
1825  {
1826  cZonePtrs[i] = new cellZone
1827  (
1828  cellZoneNames[i],
1829  zoneCells[i],
1830  i,
1831  domainMesh.cellZones()
1832  );
1833  }
1834  domainMesh.addZones(pZonePtrs, fZonePtrs, cZonePtrs);
1835 
1836  return domainMeshPtr;
1837 }
1838 
1839 
1840 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1841 
1842 Foam::fvMeshDistribute::fvMeshDistribute(fvMesh& mesh)//, const scalar mergeTol)
1843 :
1844  mesh_(mesh)
1845  //mergeTol_(mergeTol)
1846 {}
1847 
1848 
1849 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1850 
1853  const labelList& distribution
1854 )
1855 {
1856  labelList nCells(Pstream::nProcs(), Zero);
1857  forAll(distribution, celli)
1858  {
1859  label newProc = distribution[celli];
1860 
1861  if (newProc < 0 || newProc >= Pstream::nProcs())
1862  {
1864  << "Distribution should be in range 0.." << Pstream::nProcs()-1
1865  << endl
1866  << "At index " << celli << " distribution:" << newProc
1867  << abort(FatalError);
1868  }
1869  nCells[newProc]++;
1870  }
1871  return nCells;
1872 }
1873 
1874 
1877  const labelList& distribution
1878 )
1879 {
1880  // Some checks on distribution
1881  if (distribution.size() != mesh_.nCells())
1882  {
1884  << "Size of distribution:"
1885  << distribution.size() << " mesh nCells:" << mesh_.nCells()
1886  << abort(FatalError);
1887  }
1888 
1889 
1890  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1891 
1892  // Check all processors have same non-proc patches in same order.
1893  if (patches.checkParallelSync(true))
1894  {
1896  << "This application requires all non-processor patches"
1897  << " to be present in the same order on all patches" << nl
1898  << "followed by the processor patches (which of course are unique)."
1899  << nl
1900  << "Local patches:" << mesh_.boundaryMesh().names()
1901  << abort(FatalError);
1902  }
1903 
1904  // Save some data for mapping later on
1905  const label nOldPoints(mesh_.nPoints());
1906  const label nOldFaces(mesh_.nFaces());
1907  const label nOldCells(mesh_.nCells());
1908  labelList oldPatchStarts(patches.size());
1909  labelList oldPatchNMeshPoints(patches.size());
1910  forAll(patches, patchi)
1911  {
1912  oldPatchStarts[patchi] = patches[patchi].start();
1913  oldPatchNMeshPoints[patchi] = patches[patchi].nPoints();
1914  }
1915 
1916 
1917 
1918  // Short circuit trivial case.
1919  if (!Pstream::parRun())
1920  {
1921  // Collect all maps and return
1923  (
1924  mesh_,
1925 
1926  nOldPoints,
1927  nOldFaces,
1928  nOldCells,
1929  std::move(oldPatchStarts),
1930  std::move(oldPatchNMeshPoints),
1931 
1932  labelListList(one(), identity(mesh_.nPoints())), //subPointMap
1933  labelListList(one(), identity(mesh_.nFaces())), //subFaceMap
1934  labelListList(one(), identity(mesh_.nCells())), //subCellMap
1935  labelListList(one(), identity(patches.size())), //subPatchMap
1936 
1937  labelListList(one(), identity(mesh_.nPoints())), //pointMap
1938  labelListList(one(), identity(mesh_.nFaces())), //faceMap
1939  labelListList(one(), identity(mesh_.nCells())), //cellMap
1940  labelListList(one(), identity(patches.size())) //patchMap
1941  );
1942  }
1943 
1944 
1945  // Collect any zone names over all processors and shuffle zones accordingly
1946  // Note that this is not necessary for redistributePar since that already
1947  // checks for it. However other use (e.g. mesh generators) might not.
1948  const wordList pointZoneNames(mergeWordList(mesh_.pointZones().names()));
1949  reorderZones<pointZone>(pointZoneNames, mesh_.pointZones());
1950 
1951  const wordList faceZoneNames(mergeWordList(mesh_.faceZones().names()));
1952  reorderZones<faceZone>(faceZoneNames, mesh_.faceZones());
1953 
1954  const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
1955  reorderZones<cellZone>(cellZoneNames, mesh_.cellZones());
1956 
1957 
1958  // Local environment of all boundary faces
1959  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1960 
1961  // A face is uniquely defined by
1962  // - proc
1963  // - local face no
1964  //
1965  // To glue the parts of meshes which can get sent from anywhere we
1966  // need to know on boundary faces what the above tuple on both sides is.
1967  // So we need to maintain:
1968  // - original face
1969  // - original processor id (= trivial)
1970  // For coupled boundaries (where the faces are 'duplicate') we take the
1971  // lowest numbered processor as the data to store.
1972  //
1973  // Additionally to create the procboundaries we need to know where the owner
1974  // cell on the other side now is: newNeighbourProc.
1975  //
1976 
1977  // physical boundary:
1978  // sourceProc = -1
1979  // sourceNewNbrProc = -1
1980  // sourceFace = -1
1981  // sourcePatch = patchID
1982  // processor boundary:
1983  // sourceProc = proc (on owner side)
1984  // sourceNewNbrProc = distribution of coupled cell
1985  // sourceFace = face (on owner side)
1986  // sourcePatch = -1
1987  // ?cyclic:
1988  // ? sourceProc = proc
1989  // ? sourceNewNbrProc = distribution of coupled cell
1990  // ? sourceFace = face (on owner side)
1991  // ? sourcePatch = patchID
1992  // processor-cyclic boundary:
1993  // sourceProc = proc (on owner side)
1994  // sourceNewNbrProc = distribution of coupled cell
1995  // sourceFace = face (on owner side)
1996  // sourcePatch = patchID
1997 
1998  labelList sourcePatch;
1999  labelList sourceFace;
2000  labelList sourceProc;
2001  labelList sourceNewNbrProc;
2002  labelList sourcePointMaster;
2003  getCouplingData
2004  (
2005  distribution,
2006  sourceFace,
2007  sourceProc,
2008  sourcePatch,
2009  sourceNewNbrProc,
2010  sourcePointMaster
2011  );
2012 
2013 
2014  // Remove meshPhi. Since this would otherwise disappear anyway
2015  // during topo changes and we have to guarantee that all the fields
2016  // can be sent.
2017  mesh_.clearOut();
2018  mesh_.resetMotion();
2019 
2020  // Get data to send. Make sure is synchronised
2021 
2022  HashTable<wordList> allFieldNames;
2023 
2024  getFieldNames<volScalarField>(mesh_, allFieldNames);
2025  getFieldNames<volVectorField>(mesh_, allFieldNames);
2026  getFieldNames<volSphericalTensorField>(mesh_, allFieldNames);
2027  getFieldNames<volSymmTensorField>(mesh_, allFieldNames);
2028  getFieldNames<volTensorField>(mesh_, allFieldNames);
2029 
2030  getFieldNames<surfaceScalarField>(mesh_, allFieldNames);
2031  getFieldNames<surfaceVectorField>(mesh_, allFieldNames);
2032  getFieldNames<surfaceSphericalTensorField>(mesh_, allFieldNames);
2033  getFieldNames<surfaceSymmTensorField>(mesh_, allFieldNames);
2034  getFieldNames<surfaceTensorField>(mesh_, allFieldNames);
2035 
2036  getFieldNames<volScalarField::Internal>
2037  (
2038  mesh_,
2039  allFieldNames,
2040  volScalarField::typeName
2041  );
2042  getFieldNames<volVectorField::Internal>
2043  (
2044  mesh_,
2045  allFieldNames,
2046  volVectorField::typeName
2047  );
2048  getFieldNames<volSphericalTensorField::Internal>
2049  (
2050  mesh_,
2051  allFieldNames,
2052  volSphericalTensorField::typeName
2053  );
2054  getFieldNames<volSymmTensorField::Internal>
2055  (
2056  mesh_,
2057  allFieldNames,
2058  volSymmTensorField::typeName
2059  );
2060  getFieldNames<volTensorField::Internal>
2061  (
2062  mesh_,
2063  allFieldNames,
2064  volTensorField::typeName
2065  );
2066 
2067 
2068  // Find patch to temporarily put exposed and processor faces into.
2069  const label oldInternalPatchi = findNonEmptyPatch();
2070 
2071 
2072  // Delete processor patches, starting from the back. Move all faces into
2073  // oldInternalPatchi.
2074  labelList repatchFaceMap;
2075  {
2076  autoPtr<mapPolyMesh> repatchMap = deleteProcPatches(oldInternalPatchi);
2077 
2078  // Store face map (only face ordering that changed)
2079  repatchFaceMap = repatchMap().faceMap();
2080 
2081  // Reorder all boundary face data (sourceProc, sourceFace etc.)
2082  labelList bFaceMap
2083  (
2085  (
2086  repatchMap().reverseFaceMap(),
2087  mesh_.nBoundaryFaces(),
2088  mesh_.nInternalFaces()
2089  )
2090  - mesh_.nInternalFaces()
2091  );
2092 
2093  inplaceReorder(bFaceMap, sourceFace);
2094  inplaceReorder(bFaceMap, sourceProc);
2095  inplaceReorder(bFaceMap, sourcePatch);
2096  inplaceReorder(bFaceMap, sourceNewNbrProc);
2097  }
2098 
2099 
2100 
2101  // Print a bit.
2102  if (debug)
2103  {
2104  Pout<< nl << "MESH WITH PROC PATCHES DELETED:" << endl;
2105  printMeshInfo(mesh_);
2106  printFieldInfo<volScalarField>(mesh_);
2107  printFieldInfo<volVectorField>(mesh_);
2108  printFieldInfo<volSphericalTensorField>(mesh_);
2109  printFieldInfo<volSymmTensorField>(mesh_);
2110  printFieldInfo<volTensorField>(mesh_);
2111  printFieldInfo<surfaceScalarField>(mesh_);
2112  printFieldInfo<surfaceVectorField>(mesh_);
2113  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2114  printFieldInfo<surfaceSymmTensorField>(mesh_);
2115  printFieldInfo<surfaceTensorField>(mesh_);
2116  printIntFieldInfo<volScalarField::Internal>(mesh_);
2117  printIntFieldInfo<volVectorField::Internal>(mesh_);
2118  printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
2119  printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
2120  printIntFieldInfo<volTensorField::Internal>(mesh_);
2121  Pout<< nl << endl;
2122  }
2123 
2124 
2125 
2126  // Maps from subsetted mesh (that is sent) back to original maps
2127  labelListList subCellMap(Pstream::nProcs());
2128  labelListList subFaceMap(Pstream::nProcs());
2129  labelListList subPointMap(Pstream::nProcs());
2130  labelListList subPatchMap(Pstream::nProcs());
2131  // Maps from subsetted mesh to reconstructed mesh
2132  labelListList constructCellMap(Pstream::nProcs());
2133  labelListList constructFaceMap(Pstream::nProcs());
2134  labelListList constructPointMap(Pstream::nProcs());
2135  labelListList constructPatchMap(Pstream::nProcs());
2136 
2137 
2138  // Find out schedule
2139  // ~~~~~~~~~~~~~~~~~
2140 
2141  labelList nSendCells(countCells(distribution));
2142  labelList nRevcCells(Pstream::nProcs());
2143  Pstream::allToAll(nSendCells, nRevcCells);
2144 
2145  // Allocate buffers
2147 
2148 
2149  // What to send to neighbouring domains
2150  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2151 
2152  // Disable parallel.
2153  const bool oldParRun = UPstream::parRun(false);
2154 
2155  forAll(nSendCells, recvProc)
2156  {
2157  if (recvProc != Pstream::myProcNo() && nSendCells[recvProc] > 0)
2158  {
2159  // Send to recvProc
2160 
2161  if (debug)
2162  {
2163  Pout<< nl
2164  << "SUBSETTING FOR DOMAIN " << recvProc
2165  << " cells to send:"
2166  << nSendCells[recvProc]
2167  << nl << endl;
2168  }
2169 
2170  // Pstream for sending mesh and fields
2171  //OPstream str(Pstream::commsTypes::blocking, recvProc);
2172  UOPstream str(recvProc, pBufs);
2173 
2174  // Mesh subsetting engine - subset the cells of the current domain.
2175  fvMeshSubset subsetter
2176  (
2177  mesh_,
2178  recvProc,
2179  distribution,
2180  oldInternalPatchi, // oldInternalFaces patch
2181  false // no parallel sync
2182  );
2183 
2184  subCellMap[recvProc] = subsetter.cellMap();
2185  subFaceMap[recvProc] = subsetter.faceFlipMap();
2186  inplaceRenumberWithFlip
2187  (
2188  repatchFaceMap,
2189  false, // oldToNew has flip
2190  true, // subFaceMap has flip
2191  subFaceMap[recvProc]
2192  );
2193  subPointMap[recvProc] = subsetter.pointMap();
2194  subPatchMap[recvProc] = subsetter.patchMap();
2195 
2196 
2197  // Subset the boundary fields (owner/neighbour/processor)
2198  labelList procSourceFace;
2199  labelList procSourceProc;
2200  labelList procSourcePatch;
2201  labelList procSourceNewNbrProc;
2202  labelList procSourcePointMaster;
2203 
2204  subsetCouplingData
2205  (
2206  subsetter.subMesh(),
2207  subsetter.pointMap(), // from subMesh to mesh
2208  subsetter.faceMap(), // ,, ,,
2209  subsetter.cellMap(), // ,, ,,
2210 
2211  distribution, // old mesh distribution
2212  mesh_.faceOwner(), // old owner
2213  mesh_.faceNeighbour(),
2214  mesh_.nInternalFaces(),
2215 
2216  sourceFace,
2217  sourceProc,
2218  sourcePatch,
2219  sourceNewNbrProc,
2220  sourcePointMaster,
2221 
2222  procSourceFace,
2223  procSourceProc,
2224  procSourcePatch,
2225  procSourceNewNbrProc,
2226  procSourcePointMaster
2227  );
2228 
2229 
2230  // Send to neighbour
2231  sendMesh
2232  (
2233  recvProc,
2234  subsetter.subMesh(),
2235 
2236  pointZoneNames,
2237  faceZoneNames,
2238  cellZoneNames,
2239 
2240  procSourceFace,
2241  procSourceProc,
2242  procSourcePatch,
2243  procSourceNewNbrProc,
2244  procSourcePointMaster,
2245 
2246  str
2247  );
2248 
2249  // volFields
2250  sendFields<volScalarField>
2251  (
2252  recvProc,
2253  allFieldNames,
2254  subsetter,
2255  str
2256  );
2257  sendFields<volVectorField>
2258  (
2259  recvProc,
2260  allFieldNames,
2261  subsetter,
2262  str
2263  );
2264  sendFields<volSphericalTensorField>
2265  (
2266  recvProc,
2267  allFieldNames,
2268  subsetter,
2269  str
2270  );
2271  sendFields<volSymmTensorField>
2272  (
2273  recvProc,
2274  allFieldNames,
2275  subsetter,
2276  str
2277  );
2278  sendFields<volTensorField>
2279  (
2280  recvProc,
2281  allFieldNames,
2282  subsetter,
2283  str
2284  );
2285 
2286  // surfaceFields
2287  sendFields<surfaceScalarField>
2288  (
2289  recvProc,
2290  allFieldNames,
2291  subsetter,
2292  str
2293  );
2294  sendFields<surfaceVectorField>
2295  (
2296  recvProc,
2297  allFieldNames,
2298  subsetter,
2299  str
2300  );
2301  sendFields<surfaceSphericalTensorField>
2302  (
2303  recvProc,
2304  allFieldNames,
2305  subsetter,
2306  str
2307  );
2308  sendFields<surfaceSymmTensorField>
2309  (
2310  recvProc,
2311  allFieldNames,
2312  subsetter,
2313  str
2314  );
2315  sendFields<surfaceTensorField>
2316  (
2317  recvProc,
2318  allFieldNames,
2319  subsetter,
2320  str
2321  );
2322 
2323  // Dimensioned fields
2324  sendFields<volScalarField::Internal>
2325  (
2326  recvProc,
2327  allFieldNames,
2328  subsetter,
2329  str
2330  );
2331  sendFields<volVectorField::Internal>
2332  (
2333  recvProc,
2334  allFieldNames,
2335  subsetter,
2336  str
2337  );
2338  sendFields<volSphericalTensorField::Internal>
2339  (
2340  recvProc,
2341  allFieldNames,
2342  subsetter,
2343  str
2344  );
2345  sendFields<volSymmTensorField::Internal>
2346  (
2347  recvProc,
2348  allFieldNames,
2349  subsetter,
2350  str
2351  );
2352  sendFields<volTensorField::Internal>
2353  (
2354  recvProc,
2355  allFieldNames,
2356  subsetter,
2357  str
2358  );
2359  }
2360  }
2361 
2362 
2363  UPstream::parRun(oldParRun); // Restore parallel state
2364 
2365 
2366  // Start sending&receiving from buffers
2367  {
2368  if (debug)
2369  {
2370  Pout<< "Starting sending" << endl;
2371  }
2372 
2373  labelList recvSizes;
2374  pBufs.finishedSends(recvSizes);
2375 
2376  if (debug)
2377  {
2378  Pout<< "Finished sending and receiving : " << flatOutput(recvSizes)
2379  << endl;
2380  }
2381  }
2382 
2383 
2384  // Subset the part that stays
2385  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
2386 
2387  {
2388  // Save old mesh maps before changing mesh
2389  const labelList oldFaceOwner(mesh_.faceOwner());
2390  const labelList oldFaceNeighbour(mesh_.faceNeighbour());
2391  const label oldInternalFaces = mesh_.nInternalFaces();
2392 
2393  // Remove cells.
2394  autoPtr<mapPolyMesh> subMap
2395  (
2396  doRemoveCells
2397  (
2398  select(false, distribution, Pstream::myProcNo()),
2399  oldInternalPatchi
2400  )
2401  );
2402 
2403  // Addressing from subsetted mesh
2404  subCellMap[Pstream::myProcNo()] = subMap().cellMap();
2405  subFaceMap[Pstream::myProcNo()] = renumber
2406  (
2407  repatchFaceMap,
2408  subMap().faceMap()
2409  );
2410  // Insert the sign bit from face flipping
2411  labelList& faceMap = subFaceMap[Pstream::myProcNo()];
2412  forAll(faceMap, faceI)
2413  {
2414  faceMap[faceI] += 1;
2415  }
2416  const labelHashSet& flip = subMap().flipFaceFlux();
2417  for (const label facei : flip)
2418  {
2419  faceMap[facei] = -faceMap[facei];
2420  }
2421  subPointMap[Pstream::myProcNo()] = subMap().pointMap();
2422  subPatchMap[Pstream::myProcNo()] = identity(patches.size());
2423 
2424  // Subset the mesh data: neighbourCell/neighbourProc fields
2425  labelList domainSourceFace;
2426  labelList domainSourceProc;
2427  labelList domainSourcePatch;
2428  labelList domainSourceNewNbrProc;
2429  labelList domainSourcePointMaster;
2430 
2431  subsetCouplingData
2432  (
2433  mesh_, // new mesh
2434  subMap().pointMap(), // from new to original mesh
2435  subMap().faceMap(), // from new to original mesh
2436  subMap().cellMap(),
2437 
2438  distribution, // distribution before subsetting
2439  oldFaceOwner, // owner before subsetting
2440  oldFaceNeighbour, // neighbour ,,
2441  oldInternalFaces, // nInternalFaces ,,
2442 
2443  sourceFace,
2444  sourceProc,
2445  sourcePatch,
2446  sourceNewNbrProc,
2447  sourcePointMaster,
2448 
2449  domainSourceFace,
2450  domainSourceProc,
2451  domainSourcePatch,
2452  domainSourceNewNbrProc,
2453  domainSourcePointMaster
2454  );
2455 
2456  sourceFace.transfer(domainSourceFace);
2457  sourceProc.transfer(domainSourceProc);
2458  sourcePatch.transfer(domainSourcePatch);
2459  sourceNewNbrProc.transfer(domainSourceNewNbrProc);
2460  sourcePointMaster.transfer(domainSourcePointMaster);
2461  }
2462 
2463 
2464  // Print a bit.
2465  if (debug)
2466  {
2467  Pout<< nl << "STARTING MESH:" << endl;
2468  printMeshInfo(mesh_);
2469  printFieldInfo<volScalarField>(mesh_);
2470  printFieldInfo<volVectorField>(mesh_);
2471  printFieldInfo<volSphericalTensorField>(mesh_);
2472  printFieldInfo<volSymmTensorField>(mesh_);
2473  printFieldInfo<volTensorField>(mesh_);
2474  printFieldInfo<surfaceScalarField>(mesh_);
2475  printFieldInfo<surfaceVectorField>(mesh_);
2476  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2477  printFieldInfo<surfaceSymmTensorField>(mesh_);
2478  printFieldInfo<surfaceTensorField>(mesh_);
2479  printIntFieldInfo<volScalarField::Internal>(mesh_);
2480  printIntFieldInfo<volVectorField::Internal>(mesh_);
2481  printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
2482  printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
2483  printIntFieldInfo<volTensorField::Internal>(mesh_);
2484  Pout<< nl << endl;
2485  }
2486 
2487 
2488 
2489  // Receive and add what was sent
2490  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2491 
2492  // Disable parallel. Original state already known.
2493  UPstream::parRun(false);
2494 
2495  PtrList<labelList> domainSourceFaces(Pstream::nProcs());
2496  PtrList<labelList> domainSourceProcs(Pstream::nProcs());
2497  PtrList<labelList> domainSourcePatchs(Pstream::nProcs());
2498  PtrList<labelList> domainSourceNewNbrProcs(Pstream::nProcs());
2499  PtrList<labelList> domainSourcePointMasters(Pstream::nProcs());
2500 
2501  PtrList<fvMesh> domainMeshPtrs(Pstream::nProcs());
2502 
2508 
2512  (
2513  Pstream::nProcs()
2514  );
2517 
2521  (
2522  Pstream::nProcs()
2523  );
2525  (
2526  Pstream::nProcs()
2527  );
2529 
2530  forAll(nRevcCells, sendProc)
2531  {
2532  // Did processor sendProc send anything to me?
2533  if (sendProc != Pstream::myProcNo() && nRevcCells[sendProc] > 0)
2534  {
2535  if (debug)
2536  {
2537  Pout<< nl
2538  << "RECEIVING FROM DOMAIN " << sendProc
2539  << " cells to receive:"
2540  << nRevcCells[sendProc]
2541  << nl << endl;
2542  }
2543 
2544 
2545  // Pstream for receiving mesh and fields
2546  UIPstream str(sendProc, pBufs);
2547 
2548 
2549  // Receive from sendProc
2550  domainSourceFaces.set(sendProc, new labelList(0));
2551  labelList& domainSourceFace = domainSourceFaces[sendProc];
2552 
2553  domainSourceProcs.set(sendProc, new labelList(0));
2554  labelList& domainSourceProc = domainSourceProcs[sendProc];
2555 
2556  domainSourcePatchs.set(sendProc, new labelList(0));
2557  labelList& domainSourcePatch = domainSourcePatchs[sendProc];
2558 
2559  domainSourceNewNbrProcs.set(sendProc, new labelList(0));
2560  labelList& domainSourceNewNbrProc =
2561  domainSourceNewNbrProcs[sendProc];
2562 
2563  domainSourcePointMasters.set(sendProc, new labelList(0));
2564  labelList& domainSourcePointMaster =
2565  domainSourcePointMasters[sendProc];
2566 
2567  // Opposite of sendMesh
2568  {
2569  autoPtr<fvMesh> domainMeshPtr = receiveMesh
2570  (
2571  sendProc,
2572  pointZoneNames,
2573  faceZoneNames,
2574  cellZoneNames,
2575 
2576  const_cast<Time&>(mesh_.time()),
2577  domainSourceFace,
2578  domainSourceProc,
2579  domainSourcePatch,
2580  domainSourceNewNbrProc,
2581  domainSourcePointMaster,
2582  str
2583  );
2584  domainMeshPtrs.set(sendProc, domainMeshPtr.ptr());
2585  fvMesh& domainMesh = domainMeshPtrs[sendProc];
2586  // Force construction of various on mesh.
2587  //(void)domainMesh.globalData();
2588 
2589 
2590  // Receive fields. Read as single dictionary because
2591  // of problems reading consecutive fields from single stream.
2592  dictionary fieldDicts(str);
2593 
2594  // Vol fields
2595  vsfs.set(sendProc, new PtrList<volScalarField>(0));
2596  receiveFields<volScalarField>
2597  (
2598  sendProc,
2599  allFieldNames,
2600  domainMesh,
2601  vsfs[sendProc],
2602  fieldDicts
2603  );
2604  vvfs.set(sendProc, new PtrList<volVectorField>(0));
2605  receiveFields<volVectorField>
2606  (
2607  sendProc,
2608  allFieldNames,
2609  domainMesh,
2610  vvfs[sendProc],
2611  fieldDicts
2612  );
2613  vsptfs.set
2614  (
2615  sendProc,
2617  );
2618  receiveFields<volSphericalTensorField>
2619  (
2620  sendProc,
2621  allFieldNames,
2622  domainMesh,
2623  vsptfs[sendProc],
2624  fieldDicts
2625  );
2626  vsytfs.set(sendProc, new PtrList<volSymmTensorField>(0));
2627  receiveFields<volSymmTensorField>
2628  (
2629  sendProc,
2630  allFieldNames,
2631  domainMesh,
2632  vsytfs[sendProc],
2633  fieldDicts
2634  );
2635  vtfs.set(sendProc, new PtrList<volTensorField>(0));
2636  receiveFields<volTensorField>
2637  (
2638  sendProc,
2639  allFieldNames,
2640  domainMesh,
2641  vtfs[sendProc],
2642  fieldDicts
2643  );
2644 
2645  // Surface fields
2646  ssfs.set(sendProc, new PtrList<surfaceScalarField>(0));
2647  receiveFields<surfaceScalarField>
2648  (
2649  sendProc,
2650  allFieldNames,
2651  domainMesh,
2652  ssfs[sendProc],
2653  fieldDicts
2654  );
2655  svfs.set(sendProc, new PtrList<surfaceVectorField>(0));
2656  receiveFields<surfaceVectorField>
2657  (
2658  sendProc,
2659  allFieldNames,
2660  domainMesh,
2661  svfs[sendProc],
2662  fieldDicts
2663  );
2664  ssptfs.set
2665  (
2666  sendProc,
2668  );
2669  receiveFields<surfaceSphericalTensorField>
2670  (
2671  sendProc,
2672  allFieldNames,
2673  domainMesh,
2674  ssptfs[sendProc],
2675  fieldDicts
2676  );
2677  ssytfs.set(sendProc, new PtrList<surfaceSymmTensorField>(0));
2678  receiveFields<surfaceSymmTensorField>
2679  (
2680  sendProc,
2681  allFieldNames,
2682  domainMesh,
2683  ssytfs[sendProc],
2684  fieldDicts
2685  );
2686  stfs.set(sendProc, new PtrList<surfaceTensorField>(0));
2687  receiveFields<surfaceTensorField>
2688  (
2689  sendProc,
2690  allFieldNames,
2691  domainMesh,
2692  stfs[sendProc],
2693  fieldDicts
2694  );
2695 
2696  // Dimensioned fields
2697  dsfs.set
2698  (
2699  sendProc,
2701  );
2702  receiveFields<volScalarField::Internal>
2703  (
2704  sendProc,
2705  allFieldNames,
2706  domainMesh,
2707  dsfs[sendProc],
2708  fieldDicts
2709  );
2710  dvfs.set
2711  (
2712  sendProc,
2714  );
2715  receiveFields<volVectorField::Internal>
2716  (
2717  sendProc,
2718  allFieldNames,
2719  domainMesh,
2720  dvfs[sendProc],
2721  fieldDicts
2722  );
2723  dstfs.set
2724  (
2725  sendProc,
2727  );
2728  receiveFields<volSphericalTensorField::Internal>
2729  (
2730  sendProc,
2731  allFieldNames,
2732  domainMesh,
2733  dstfs[sendProc],
2734  fieldDicts
2735  );
2736  dsytfs.set
2737  (
2738  sendProc,
2740  );
2741  receiveFields<volSymmTensorField::Internal>
2742  (
2743  sendProc,
2744  allFieldNames,
2745  domainMesh,
2746  dsytfs[sendProc],
2747  fieldDicts
2748  );
2749  dtfs.set
2750  (
2751  sendProc,
2753  );
2754  receiveFields<volTensorField::Internal>
2755  (
2756  sendProc,
2757  allFieldNames,
2758  domainMesh,
2759  dtfs[sendProc],
2760  fieldDicts
2761  );
2762  }
2763  }
2764  }
2765 
2766  // Clear out storage
2767  pBufs.clear();
2768 
2769 
2770  // Set up pointers to meshes so we can include our mesh_
2771  UPtrList<polyMesh> meshes(domainMeshPtrs.size());
2772  UPtrList<fvMesh> fvMeshes(domainMeshPtrs.size());
2773  forAll(domainMeshPtrs, proci)
2774  {
2775  if (domainMeshPtrs.set(proci))
2776  {
2777  meshes.set(proci, &domainMeshPtrs[proci]);
2778  fvMeshes.set(proci, &domainMeshPtrs[proci]);
2779  }
2780  }
2781 
2782  // 'Receive' from myself
2783  {
2784  meshes.set(Pstream::myProcNo(), &mesh_);
2785  fvMeshes.set(Pstream::myProcNo(), &mesh_);
2786 
2787  //domainSourceFaces.set(Pstream::myProcNo(), std::move(sourceFace));
2788  domainSourceFaces.set(Pstream::myProcNo(), new labelList(0));
2789  domainSourceFaces[Pstream::myProcNo()] = sourceFace;
2790 
2791  domainSourceProcs.set(Pstream::myProcNo(), new labelList(0));
2792  //std::move(sourceProc));
2793  domainSourceProcs[Pstream::myProcNo()] = sourceProc;
2794 
2795  domainSourcePatchs.set(Pstream::myProcNo(), new labelList(0));
2796  //, std::move(sourcePatch));
2797  domainSourcePatchs[Pstream::myProcNo()] = sourcePatch;
2798 
2799  domainSourceNewNbrProcs.set(Pstream::myProcNo(), new labelList(0));
2800  domainSourceNewNbrProcs[Pstream::myProcNo()] = sourceNewNbrProc;
2801 
2802  domainSourcePointMasters.set(Pstream::myProcNo(), new labelList(0));
2803  domainSourcePointMasters[Pstream::myProcNo()] = sourcePointMaster;
2804  }
2805 
2806 
2807  // Find matching faces that need to be stitched
2808  labelListList localBoundaryFace(Pstream::nProcs());
2809  labelListList remoteFaceProc(Pstream::nProcs());
2810  labelListList remoteBoundaryFace(Pstream::nProcs());
2811  findCouples
2812  (
2813  meshes,
2814  domainSourceFaces,
2815  domainSourceProcs,
2816  domainSourcePatchs,
2817 
2818  localBoundaryFace,
2819  remoteFaceProc,
2820  remoteBoundaryFace
2821  );
2822 
2823 
2824  const label nOldInternalFaces = mesh_.nInternalFaces();
2825  const labelList oldFaceOwner(mesh_.faceOwner());
2826 
2828  (
2829  Pstream::myProcNo(), // index of mesh to modify (== mesh_)
2830  fvMeshes,
2831  oldFaceOwner,
2832 
2833  // Coupling info
2834  localBoundaryFace,
2835  remoteFaceProc,
2836  remoteBoundaryFace,
2837 
2838  constructPatchMap,
2839  constructCellMap,
2840  constructFaceMap,
2841  constructPointMap
2842  );
2843 
2844  if (debug)
2845  {
2846  Pout<< nl << "ADDED REMOTE MESHES:" << endl;
2847  printMeshInfo(mesh_);
2848  printFieldInfo<volScalarField>(mesh_);
2849  printFieldInfo<volVectorField>(mesh_);
2850  printFieldInfo<volSphericalTensorField>(mesh_);
2851  printFieldInfo<volSymmTensorField>(mesh_);
2852  printFieldInfo<volTensorField>(mesh_);
2853  printFieldInfo<surfaceScalarField>(mesh_);
2854  printFieldInfo<surfaceVectorField>(mesh_);
2855  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2856  printFieldInfo<surfaceSymmTensorField>(mesh_);
2857  printFieldInfo<surfaceTensorField>(mesh_);
2858  printIntFieldInfo<volScalarField::Internal>(mesh_);
2859  printIntFieldInfo<volVectorField::Internal>(mesh_);
2860  printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
2861  printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
2862  printIntFieldInfo<volTensorField::Internal>(mesh_);
2863  Pout<< nl << endl;
2864  }
2865 
2866  {
2867  //- Combine sourceProc, sourcePatch, sourceFace
2868  sourceProc.setSize(mesh_.nBoundaryFaces());
2869  sourceProc = -1;
2870  sourcePatch.setSize(mesh_.nBoundaryFaces());
2871  sourcePatch = -1;
2872  sourceFace.setSize(mesh_.nBoundaryFaces());
2873  sourceFace = -1;
2874  sourceNewNbrProc.setSize(mesh_.nBoundaryFaces());
2875  sourceNewNbrProc = -1;
2876  sourcePointMaster.setSize(mesh_.nPoints());
2877  sourcePointMaster = -1;
2878 
2879  if (mesh_.nPoints() > 0)
2880  {
2881  forAll(meshes, meshi)
2882  {
2883  if (domainSourceFaces.set(meshi))
2884  {
2885  const label nIntFaces =
2886  (
2887  meshi == Pstream::myProcNo()
2888  ? nOldInternalFaces
2889  : meshes[meshi].nInternalFaces()
2890  );
2891  const labelList& faceOwner
2892  (
2893  meshi == Pstream::myProcNo()
2894  ? oldFaceOwner
2895  : meshes[meshi].faceOwner()
2896  );
2897 
2898  labelList& faceMap = constructFaceMap[meshi];
2899  const labelList& cellMap = constructCellMap[meshi];
2900 
2901  const labelList& domainSourceFace =
2902  domainSourceFaces[meshi];
2903  const labelList& domainSourceProc =
2904  domainSourceProcs[meshi];
2905  const labelList& domainSourcePatch =
2906  domainSourcePatchs[meshi];
2907  const labelList& domainSourceNewNbr =
2908  domainSourceNewNbrProcs[meshi];
2910  (
2911  sourcePointMaster,
2912  constructPointMap[meshi]
2913  ) = domainSourcePointMasters[meshi];
2914 
2915 
2916  forAll(domainSourceFace, bFacei)
2917  {
2918  const label oldFacei = bFacei+nIntFaces;
2919  const label allFacei = faceMap[oldFacei];
2920  const label allbFacei = allFacei-mesh_.nInternalFaces();
2921 
2922  if (allbFacei >= 0)
2923  {
2924  sourceProc[allbFacei] = domainSourceProc[bFacei];
2925  sourcePatch[allbFacei] = domainSourcePatch[bFacei];
2926  sourceFace[allbFacei] = domainSourceFace[bFacei];
2927  sourceNewNbrProc[allbFacei] =
2928  domainSourceNewNbr[bFacei];
2929  }
2930  }
2931 
2932 
2933  // Add flip to constructFaceMap
2934  forAll(faceMap, oldFacei)
2935  {
2936  const label allFacei = faceMap[oldFacei];
2937  const label allOwn = mesh_.faceOwner()[allFacei];
2938 
2939  if (cellMap[faceOwner[oldFacei]] == allOwn)
2940  {
2941  // Master face
2942  faceMap[oldFacei] += 1;
2943  }
2944  else
2945  {
2946  // Slave face. Flip.
2947  faceMap[oldFacei] = -faceMap[oldFacei] - 1;
2948  }
2949  }
2950  }
2951  }
2952  }
2953  }
2954 
2955 
2956  UPstream::parRun(oldParRun); // Restore parallel state
2957 
2958 
2959  // Print a bit.
2960  if (debug)
2961  {
2962  Pout<< nl << "REDISTRIBUTED MESH:" << endl;
2963  printMeshInfo(mesh_);
2964  printFieldInfo<volScalarField>(mesh_);
2965  printFieldInfo<volVectorField>(mesh_);
2966  printFieldInfo<volSphericalTensorField>(mesh_);
2967  printFieldInfo<volSymmTensorField>(mesh_);
2968  printFieldInfo<volTensorField>(mesh_);
2969  printFieldInfo<surfaceScalarField>(mesh_);
2970  printFieldInfo<surfaceVectorField>(mesh_);
2971  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2972  printFieldInfo<surfaceSymmTensorField>(mesh_);
2973  printFieldInfo<surfaceTensorField>(mesh_);
2974  printIntFieldInfo<volScalarField::Internal>(mesh_);
2975  printIntFieldInfo<volVectorField::Internal>(mesh_);
2976  printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
2977  printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
2978  printIntFieldInfo<volTensorField::Internal>(mesh_);
2979  Pout<< nl << endl;
2980  }
2981 
2982 
2983  // See if any originally shared points need to be merged. Note: does
2984  // parallel comms. After this points and edges should again be consistent.
2985  mergeSharedPoints(sourcePointMaster, constructPointMap);
2986 
2987 
2988  // Add processorPatches
2989  // ~~~~~~~~~~~~~~~~~~~~
2990 
2991  // Per neighbour processor, per originating patch, the patchID
2992  // For faces resulting from internal faces or normal processor patches
2993  // the originating patch is -1. For cyclics this is the cyclic patchID.
2994  List<Map<label>> procPatchID;
2995 
2996  // Add processor and processorCyclic patches.
2997  addProcPatches(sourceNewNbrProc, sourcePatch, procPatchID);
2998 
2999  // Put faces into correct patch. Note that we now have proper
3000  // processorPolyPatches again so repatching will take care of coupled face
3001  // ordering.
3002 
3003  // Get boundary faces to be repatched. Is -1 or new patchID
3004  labelList newPatchID
3005  (
3006  getBoundaryPatch
3007  (
3008  sourceNewNbrProc,
3009  sourcePatch,
3010  procPatchID
3011  )
3012  );
3013 
3014  // Change patches. Since this might change ordering of coupled faces
3015  // we also need to adapt our constructMaps.
3016  repatch(newPatchID, constructFaceMap);
3017 
3018  // Bit of hack: processorFvPatchField does not get reset since created
3019  // from nothing so explicitly reset.
3020  initPatchFields<volScalarField, processorFvPatchField<scalar>>
3021  (
3022  Zero
3023  );
3024  initPatchFields<volVectorField, processorFvPatchField<vector>>
3025  (
3026  Zero
3027  );
3028  initPatchFields
3029  <
3032  >
3033  (
3034  Zero
3035  );
3036  initPatchFields<volSymmTensorField, processorFvPatchField<symmTensor>>
3037  (
3038  Zero
3039  );
3040  initPatchFields<volTensorField, processorFvPatchField<tensor>>
3041  (
3042  Zero
3043  );
3044 
3045 
3046  mesh_.setInstance(mesh_.time().timeName());
3047 
3048 
3049  // Print a bit
3050  if (debug)
3051  {
3052  Pout<< nl << "FINAL MESH:" << endl;
3053  printMeshInfo(mesh_);
3054  printFieldInfo<volScalarField>(mesh_);
3055  printFieldInfo<volVectorField>(mesh_);
3056  printFieldInfo<volSphericalTensorField>(mesh_);
3057  printFieldInfo<volSymmTensorField>(mesh_);
3058  printFieldInfo<volTensorField>(mesh_);
3059  printFieldInfo<surfaceScalarField>(mesh_);
3060  printFieldInfo<surfaceVectorField>(mesh_);
3061  printFieldInfo<surfaceSphericalTensorField>(mesh_);
3062  printFieldInfo<surfaceSymmTensorField>(mesh_);
3063  printFieldInfo<surfaceTensorField>(mesh_);
3064  printIntFieldInfo<volScalarField::Internal>(mesh_);
3065  printIntFieldInfo<volVectorField::Internal>(mesh_);
3066  printIntFieldInfo<volSphericalTensorField::Internal>(mesh_);
3067  printIntFieldInfo<volSymmTensorField::Internal>(mesh_);
3068  printIntFieldInfo<volTensorField::Internal>(mesh_);
3069  Pout<< nl << endl;
3070  }
3071 
3072  // Collect all maps and return
3074  (
3075  mesh_,
3076 
3077  nOldPoints,
3078  nOldFaces,
3079  nOldCells,
3080  std::move(oldPatchStarts),
3081  std::move(oldPatchNMeshPoints),
3082 
3083  std::move(subPointMap),
3084  std::move(subFaceMap),
3085  std::move(subCellMap),
3086  std::move(subPatchMap),
3087 
3088  std::move(constructPointMap),
3089  std::move(constructFaceMap),
3090  std::move(constructCellMap),
3091  std::move(constructPatchMap),
3092 
3093  true, // subFaceMap has flip
3094  true // constructFaceMap has flip
3095  );
3096 }
3097 
3098 
3099 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::fvMeshDistribute::countCells
static labelList countCells(const labelList &)
Helper function: count cells per processor in wanted distribution.
Definition: fvMeshDistribute.C:1852
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1069
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::distribution
Accumulating histogram of values. Specified bin resolution automatic generation of bins.
Definition: distribution.H:61
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::one
static const Vector< scalar > one
Definition: VectorSpace.H:116
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
polyRemovePoint.H
cyclicACMIPolyPatch.H
Foam::UOPstream
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:57
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
processorFvPatchField.H
Foam::fvMeshSubset::cellMap
const labelList & cellMap() const
Return cell map.
Definition: fvMeshSubsetI.H:91
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::fvMeshSubset::pointMap
const labelList & pointMap() const
Return point map.
Definition: fvMeshSubsetI.H:64
Foam::polyMesh::defaultRegion
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:318
Foam::processorFvPatchField
This boundary condition enables processor communication across patches.
Definition: processorFvPatchField.H:66
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::fvMeshSubset
Given the original mesh and the list of selected cells, it creates the mesh consisting only of the de...
Definition: fvMeshSubset.H:73
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::HashTableOps::values
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:149
Foam::fvPatch::start
virtual label start() const
Return start label of this patch in the polyMesh face list.
Definition: fvPatch.H:173
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:54
globalIndex.H
Foam::pointZone
A subset of mesh points.
Definition: pointZone.H:65
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:88
Foam::polyPatch::coupled
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:377
polyTopoChange.H
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:780
Foam::fvsPatchField
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
Definition: fvsPatchField.H:68
Foam::glTF::key
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
Foam::one
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:61
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Am I the master process.
Definition: UPstream.H:457
Foam::syncTools::swapBoundaryFaceList
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:445
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
Definition: gatherScatter.C:150
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
surfaceFields.H
Foam::surfaceFields.
Foam::PtrList::set
const T * set(const label i) const
Return const pointer to element (can be nullptr),.
Definition: PtrList.H:138
removeCells.H
Foam::fvPatch::name
virtual const word & name() const
Return name.
Definition: fvPatch.H:167
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::PstreamBuffers::clear
void clear()
Reset (clear) individual buffers and reset state.
Definition: PstreamBuffers.C:125
Foam::cellZoneMesh
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
Definition: cellZoneMeshFwd.H:44
Foam::sign
dimensionedScalar sign(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:166
Foam::HashSet< label, Hash< label > >
Foam::pointZoneMesh
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
Definition: pointZoneMeshFwd.H:44
syncTools.H
processorCyclicPolyPatch.H
Foam::polyBoundaryMesh::start
label start() const
The start label of the boundary faces in the polyMesh face list.
Definition: polyBoundaryMesh.C:611
Foam::fvMeshSubset::faceFlipMap
const labelList & faceFlipMap() const
Return face map with sign to encode flipped faces.
Definition: fvMeshSubsetI.H:80
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:61
Foam::polyBoundaryMesh::names
wordList names() const
Return a list of patch names.
Definition: polyBoundaryMesh.C:555
fvMeshAdder.H
Foam::fvMeshDistribute::generateTestField
static tmp< surfaceScalarField > generateTestField(const fvMesh &)
Generate a test field on faces.
Definition: fvMeshDistribute.C:405
Foam::primitiveMesh::nPoints
label nPoints() const noexcept
Number of mesh points.
Definition: primitiveMeshI.H:37
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
processorFvsPatchField.H
Foam::cellZone
A subset of mesh cells.
Definition: cellZone.H:62
Foam::fvMeshAdder::add
static autoPtr< mapAddedPolyMesh > add(fvMesh &mesh0, const fvMesh &mesh1, const faceCoupleInfo &coupleInfo, const bool validBoundary=true, const bool fullyMapped=false)
Inplace add mesh to fvMesh. Maps all stored fields. Returns map.
Definition: fvMeshAdder.C:74
Foam::fvBoundaryMesh
Foam::fvBoundaryMesh.
Definition: fvBoundaryMesh.H:57
Foam::labelPair
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:54
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:62
PstreamCombineReduceOps.H
Combination-Reduction operation for a parallel run. The information from all nodes is collected on th...
Foam::faceZoneMesh
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
Definition: faceZoneMeshFwd.H:44
mapDistributePolyMesh.H
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::polyBoundaryMesh::checkParallelSync
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order. Return.
Definition: polyBoundaryMesh.C:972
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::primitiveMesh::nCells
label nCells() const noexcept
Number of mesh cells.
Definition: primitiveMeshI.H:96
labelPairHashes.H
A HashTable to objects of type <T> with a labelPair key. The hashing is based on labelPair (FixedList...
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:227
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
Foam::Field< scalar >
Foam::fvMeshSubset::subMesh
const fvMesh & subMesh() const
Return reference to subset mesh.
Definition: fvMeshSubsetI.H:48
Foam::polyPatch::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:315
Foam::fvMesh::magSf
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
Definition: fvMeshGeometry.C:330
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::polyMesh::cellZones
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:492
Foam::OSstream::name
virtual const fileName & name() const
Get the name of the stream.
Definition: OSstream.H:107
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
meshes
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1107
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:456
Foam::primitiveMesh::nBoundaryFaces
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
Definition: primitiveMeshI.H:84
processorCyclicFvPatchField.H
Foam::UPtrList
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: UPtrList.H:62
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:486
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:42
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:59
Foam::fvMeshTools::reorderPatches
static void reorderPatches(fvMesh &, const labelList &oldToNew, const label nPatches, const bool validBoundary)
Reorder and remove trailing patches. If validBoundary call is parallel.
Definition: fvMeshTools.C:329
Foam::autoPtr::ptr
T * ptr() noexcept
Same as release().
Definition: autoPtr.H:172
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
Foam::labelPairLookup
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....
Definition: labelPairHashes.H:67
Foam::lessProcPatches::lessProcPatches
lessProcPatches(const labelList &nbrProc, const labelList &referPatchID)
Definition: fvMeshDistribute.C:66
Foam::PstreamBuffers::finishedSends
void finishedSends(const bool block=true)
Mark all sends as having been done.
Definition: PstreamBuffers.C:73
faceCoupleInfo.H
newPointi
label newPointi
Definition: readKivaGrid.H:496
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::polyPatch::New
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return pointer to a new patch created on freestore from components.
Definition: polyPatchNew.C:35
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:216
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:361
polyModifyFace.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::HashTable< wordList >
Foam::indirectPrimitivePatch
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
Definition: indirectPrimitivePatch.H:49
Foam::normalised
VectorSpace< Form, Cmpt, Ncmpts > normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:487
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::fvMesh::boundary
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:685
Foam::IOobject::name
const word & name() const noexcept
Return name.
Definition: IOobjectI.H:65
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::fvMeshDistribute::printMeshInfo
static void printMeshInfo(const fvMesh &)
Print some info on mesh.
Definition: fvMeshDistribute.C:225
Foam::renumber
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:37
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::lessProcPatches::operator()
bool operator()(const label a, const label b)
Definition: fvMeshDistribute.C:72
Foam::UPstream::commsTypes::nonBlocking
fvMeshDistribute.H
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:463
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::fvsPatchField::patch
const fvPatch & patch() const
Return patch.
Definition: fvsPatchField.H:281
Foam::zoneIdentifier::name
const word & name() const noexcept
The zone name.
Definition: zoneIdentifier.H:123
fvMeshTools.H
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::Vector< scalar >
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const noexcept
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::UPstream::parRun
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
Foam::List< label >
Foam::fvMeshDistribute::printCoupleInfo
static void printCoupleInfo(const primitiveMesh &, const labelList &, const labelList &, const labelList &, const labelList &)
Print some info on coupling data.
Definition: fvMeshDistribute.C:285
Foam::fvMeshTools::addPatch
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:37
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::primitiveMesh::faceCentres
const vectorField & faceCentres() const
Definition: primitiveMeshFaceCentresAndAreas.C:77
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::polyMesh::pointZones
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition: polyMesh.H:480
Foam::fvMeshDistribute::testField
static void testField(const surfaceScalarField &)
Check whether field consistent with face orientation.
Definition: fvMeshDistribute.C:455
Foam::fvMeshDistribute::distribute
autoPtr< mapDistributePolyMesh > distribute(const labelList &dist)
Send cells to neighbours according to distribution.
Definition: fvMeshDistribute.C:1876
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::HashTable::set
bool set(const Key &key, const T &obj)
Copy assign a new entry, overwriting existing entries.
Definition: HashTableI.H:202
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
Foam::fvMeshSubset::faceMap
const labelList & faceMap() const
Return face map.
Definition: fvMeshSubsetI.H:72
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
forAllReverse
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:309
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:280
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:60
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:124
Foam::primitiveMesh::nFaces
label nFaces() const noexcept
Number of mesh faces.
Definition: primitiveMeshI.H:90
Foam::patchIdentifier::name
const word & name() const noexcept
The patch name.
Definition: patchIdentifier.H:135
ListOps.H
Various functions to operate on Lists.
CompactListList.H
Foam::sortedOrder
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
Foam::volSphericalTensorField
GeometricField< sphericalTensor, fvPatchField, volMesh > volSphericalTensorField
Definition: volFieldsFwd.H:64
Foam::UIPstream
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:56
Foam::fvMeshSubset::patchMap
const labelList & patchMap() const
Return patch map.
Definition: fvMeshSubsetI.H:99
Foam::labelUList
UList< label > labelUList
A UList of labels.
Definition: UList.H:85
Foam::GeometricField< scalar, fvsPatchField, surfaceMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::UPstream::allToAll
static void allToAll(const labelUList &sendData, labelUList &recvData, const label communicator=worldComm)
Exchange label with all processors (in the communicator).
Definition: UPstream.C:172
Foam::PtrListOps::names
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::polyMeshAdder::mergePoints
static void mergePoints(const polyMesh &, const Map< label > &pointToMaster, polyTopoChange &meshMod)
Helper: Merge points.
Definition: polyMeshAdder.C:2198
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1113
Foam::lessProcPatches
Less function class that can be used for sorting processor patches.
Definition: fvMeshDistribute.C:59
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Number of processes in parallel run, and 1 for serial run.
Definition: UPstream.H:445
Foam::dimless
const dimensionSet dimless
Dimensionless.
Definition: dimensionSets.C:189
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:58
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265
mappedPatchBase.H
Foam::fvMesh::Sf
const surfaceVectorField & Sf() const
Return cell face area vectors.
Definition: fvMeshGeometry.C:319
Foam::primitiveMesh
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:78