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-2020 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  Pstream::scatterList(allNames);
205 
206  wordHashSet mergedNames;
207  forAll(allNames, proci)
208  {
209  mergedNames.insert(allNames[proci]);
210  }
211  return mergedNames.sortedToc();
212 }
213 
214 
216 {
217  Pout<< "Primitives:" << nl
218  << " points :" << mesh.nPoints() << nl
219  << " bb :" << boundBox(mesh.points(), false) << nl
220  << " internalFaces:" << mesh.nInternalFaces() << nl
221  << " faces :" << mesh.nFaces() << nl
222  << " cells :" << mesh.nCells() << nl;
223 
224  const fvBoundaryMesh& patches = mesh.boundary();
225 
226  Pout<< "Patches:" << endl;
227  forAll(patches, patchi)
228  {
229  const polyPatch& pp = patches[patchi].patch();
230 
231  Pout<< " " << patchi << " name:" << pp.name()
232  << " size:" << pp.size()
233  << " start:" << pp.start()
234  << " type:" << pp.type()
235  << endl;
236  }
237 
238  if (mesh.pointZones().size())
239  {
240  Pout<< "PointZones:" << endl;
241  forAll(mesh.pointZones(), zoneI)
242  {
243  const pointZone& pz = mesh.pointZones()[zoneI];
244  Pout<< " " << zoneI << " name:" << pz.name()
245  << " size:" << pz.size()
246  << endl;
247  }
248  }
249  if (mesh.faceZones().size())
250  {
251  Pout<< "FaceZones:" << endl;
252  forAll(mesh.faceZones(), zoneI)
253  {
254  const faceZone& fz = mesh.faceZones()[zoneI];
255  Pout<< " " << zoneI << " name:" << fz.name()
256  << " size:" << fz.size()
257  << endl;
258  }
259  }
260  if (mesh.cellZones().size())
261  {
262  Pout<< "CellZones:" << endl;
263  forAll(mesh.cellZones(), zoneI)
264  {
265  const cellZone& cz = mesh.cellZones()[zoneI];
266  Pout<< " " << zoneI << " name:" << cz.name()
267  << " size:" << cz.size()
268  << endl;
269  }
270  }
271 }
272 
273 
275 (
276  const primitiveMesh& mesh,
277  const labelList& sourceFace,
278  const labelList& sourceProc,
279  const labelList& sourcePatch,
280  const labelList& sourceNewNbrProc
281 )
282 {
283  Pout<< nl
284  << "Current coupling info:"
285  << endl;
286 
287  forAll(sourceFace, bFacei)
288  {
289  label meshFacei = mesh.nInternalFaces() + bFacei;
290 
291  Pout<< " meshFace:" << meshFacei
292  << " fc:" << mesh.faceCentres()[meshFacei]
293  << " connects to proc:" << sourceProc[bFacei]
294  << "/face:" << sourceFace[bFacei]
295  << " which will move to proc:" << sourceNewNbrProc[bFacei]
296  << endl;
297  }
298 }
299 
300 
301 Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
302 {
303  // Finds (non-empty) patch that exposed internal and proc faces can be
304  // put into.
305  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
306 
307 
308  // Mark 'special' patches : -coupled, -duplicate faces. These probably
309  // should not be used to (temporarily) store processor faces ...
310 
311  bitSet isCoupledPatch(patches.size());
312  forAll(patches, patchi)
313  {
314  const polyPatch& pp = patches[patchi];
315 
316  if (isA<cyclicACMIPolyPatch>(pp))
317  {
318  isCoupledPatch.set(patchi);
319  const cyclicACMIPolyPatch& cpp =
320  refCast<const cyclicACMIPolyPatch>(pp);
321  const label dupPatchID = cpp.nonOverlapPatchID();
322  if (dupPatchID != -1)
323  {
324  isCoupledPatch.set(dupPatchID);
325  }
326  }
327  else if (pp.coupled())
328  {
329  isCoupledPatch.set(patchi);
330  }
331  }
332 
333  label nonEmptyPatchi = -1;
334 
335  forAllReverse(patches, patchi)
336  {
337  const polyPatch& pp = patches[patchi];
338 
339  if
340  (
341  !isA<emptyPolyPatch>(pp)
342  && !isCoupledPatch(patchi)
343  && !isA<mappedPatchBase>(pp)
344  )
345  {
346  nonEmptyPatchi = patchi;
347  break;
348  }
349  }
350 
351  if (nonEmptyPatchi == -1)
352  {
354  << "Cannot find a patch which is neither of type empty nor"
355  << " coupled in patches " << patches.names() << endl
356  << "There has to be at least one such patch for"
357  << " distribution to work" << abort(FatalError);
358  }
359 
360  if (debug)
361  {
362  Pout<< "findNonEmptyPatch : using patch " << nonEmptyPatchi
363  << " name:" << patches[nonEmptyPatchi].name()
364  << " type:" << patches[nonEmptyPatchi].type()
365  << " to put exposed faces into." << endl;
366  }
367 
368 
369  // Do additional test for processor patches intermingled with non-proc
370  // patches.
371  label procPatchi = -1;
372 
373  forAll(patches, patchi)
374  {
375  if (isA<processorPolyPatch>(patches[patchi]))
376  {
377  procPatchi = patchi;
378  }
379  else if (procPatchi != -1)
380  {
382  << "Processor patches should be at end of patch list."
383  << endl
384  << "Have processor patch " << procPatchi
385  << " followed by non-processor patch " << patchi
386  << " in patches " << patches.names()
387  << abort(FatalError);
388  }
389  }
390 
391  return nonEmptyPatchi;
392 }
393 
394 
396 (
397  const fvMesh& mesh
398 )
399 {
400  const vector testNormal = normalised(vector::one);
401 
403  (
405  (
406  IOobject
407  (
408  "myFlux",
409  mesh.time().timeName(),
410  mesh,
413  ),
414  mesh,
416  )
417  );
418  surfaceScalarField& fld = tfld.ref();
419 
420  const surfaceVectorField n(mesh.Sf()/mesh.magSf());
421 
422  forAll(fld, facei)
423  {
424  fld[facei] = (n[facei] & testNormal);
425  }
426 
427  surfaceScalarField::Boundary& fluxBf = fld.boundaryFieldRef();
428  const surfaceVectorField::Boundary& nBf = n.boundaryField();
429 
430  forAll(fluxBf, patchi)
431  {
432  fvsPatchScalarField& fvp = fluxBf[patchi];
433 
434  scalarField newPfld(fvp.size());
435  forAll(newPfld, i)
436  {
437  newPfld[i] = (nBf[patchi][i] & testNormal);
438  }
439  fvp == newPfld;
440  }
441 
442  return tfld;
443 }
444 
445 
447 {
448  const fvMesh& mesh = fld.mesh();
449 
450  const vector testNormal = normalised(vector::one);
451 
452  const surfaceVectorField n(mesh.Sf()/mesh.magSf());
453 
454  forAll(fld, facei)
455  {
456  scalar cos = (n[facei] & testNormal);
457 
458  if (mag(cos - fld[facei]) > 1e-6)
459  {
460  //FatalErrorInFunction
462  << "On internal face " << facei << " at "
463  << mesh.faceCentres()[facei]
464  << " the field value is " << fld[facei]
465  << " whereas cos angle of " << testNormal
466  << " with mesh normal " << n[facei]
467  << " is " << cos
468  //<< exit(FatalError);
469  << endl;
470  }
471  }
472  forAll(fld.boundaryField(), patchi)
473  {
474  const fvsPatchScalarField& fvp = fld.boundaryField()[patchi];
475  const fvsPatchVectorField& np = n.boundaryField()[patchi];
476 
477  forAll(fvp, i)
478  {
479  scalar cos = (np[i] & testNormal);
480 
481  if (mag(cos - fvp[i]) > 1e-6)
482  {
483  label facei = fvp.patch().start()+i;
484  //FatalErrorInFunction
486  << "On face " << facei
487  << " on patch " << fvp.patch().name()
488  << " at " << mesh.faceCentres()[facei]
489  << " the field value is " << fvp[i]
490  << " whereas cos angle of " << testNormal
491  << " with mesh normal " << np[i]
492  << " is " << cos
493  //<< exit(FatalError);
494  << endl;
495  }
496  }
497  }
498 }
499 
500 
501 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::deleteProcPatches
502 (
503  const label destinationPatch
504 )
505 {
506  // Delete all processor patches. Move any processor faces into the last
507  // non-processor patch.
508 
509  // New patchID per boundary faces to be repatched. Is -1 (no change)
510  // or new patchID
511  labelList newPatchID(mesh_.nBoundaryFaces(), -1);
512 
513  label nProcPatches = 0;
514 
515  forAll(mesh_.boundaryMesh(), patchi)
516  {
517  const polyPatch& pp = mesh_.boundaryMesh()[patchi];
518 
519  if (isA<processorPolyPatch>(pp))
520  {
521  if (debug)
522  {
523  Pout<< "Moving all faces of patch " << pp.name()
524  << " into patch " << destinationPatch
525  << endl;
526  }
527 
528  label offset = pp.start() - mesh_.nInternalFaces();
529 
530  forAll(pp, i)
531  {
532  newPatchID[offset+i] = destinationPatch;
533  }
534 
535  nProcPatches++;
536  }
537  }
538 
539  // Note: order of boundary faces been kept the same since the
540  // destinationPatch is at the end and we have visited the patches in
541  // incremental order.
542  labelListList dummyFaceMaps;
543  autoPtr<mapPolyMesh> map = repatch(newPatchID, dummyFaceMaps);
544 
545 
546  // Delete (now empty) processor patches.
547  {
548  labelList oldToNew(identity(mesh_.boundaryMesh().size()));
549  label newi = 0;
550  // Non processor patches first
551  forAll(mesh_.boundaryMesh(), patchi)
552  {
553  if (!isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
554  {
555  oldToNew[patchi] = newi++;
556  }
557  }
558  label nNonProcPatches = newi;
559 
560  // Processor patches as last
561  forAll(mesh_.boundaryMesh(), patchi)
562  {
563  if (isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
564  {
565  oldToNew[patchi] = newi++;
566  }
567  }
568  fvMeshTools::reorderPatches(mesh_, oldToNew, nNonProcPatches, false);
569  }
570 
571  return map;
572 }
573 
574 
575 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
576 (
577  const labelList& newPatchID, // per boundary face -1 or new patchID
578  labelListList& constructFaceMap
579 )
580 {
581  polyTopoChange meshMod(mesh_);
582 
583  forAll(newPatchID, bFacei)
584  {
585  if (newPatchID[bFacei] != -1)
586  {
587  label facei = mesh_.nInternalFaces() + bFacei;
588 
589  label zoneID = mesh_.faceZones().whichZone(facei);
590  bool zoneFlip = false;
591 
592  if (zoneID >= 0)
593  {
594  const faceZone& fZone = mesh_.faceZones()[zoneID];
595  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
596  }
597 
598  meshMod.setAction
599  (
600  polyModifyFace
601  (
602  mesh_.faces()[facei], // modified face
603  facei, // label of face
604  mesh_.faceOwner()[facei], // owner
605  -1, // neighbour
606  false, // face flip
607  newPatchID[bFacei], // patch for face
608  false, // remove from zone
609  zoneID, // zone for face
610  zoneFlip // face flip in zone
611  )
612  );
613  }
614  }
615 
616 
617  // Do mapping of fields from one patchField to the other ourselves since
618  // is currently not supported by updateMesh.
619 
620  // Store boundary fields (we only do this for surfaceFields)
621  PtrList<FieldField<fvsPatchField, scalar>> sFlds;
622  saveBoundaryFields<scalar, surfaceMesh>(sFlds);
623  PtrList<FieldField<fvsPatchField, vector>> vFlds;
624  saveBoundaryFields<vector, surfaceMesh>(vFlds);
625  PtrList<FieldField<fvsPatchField, sphericalTensor>> sptFlds;
626  saveBoundaryFields<sphericalTensor, surfaceMesh>(sptFlds);
627  PtrList<FieldField<fvsPatchField, symmTensor>> sytFlds;
628  saveBoundaryFields<symmTensor, surfaceMesh>(sytFlds);
629  PtrList<FieldField<fvsPatchField, tensor>> tFlds;
630  saveBoundaryFields<tensor, surfaceMesh>(tFlds);
631 
632  // Change the mesh (no inflation). Note: parallel comms allowed.
633  //
634  // NOTE: there is one very particular problem with this ordering.
635  // We first create the processor patches and use these to merge out
636  // shared points (see mergeSharedPoints below). So temporarily points
637  // and edges do not match!
638 
639  autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
640  mapPolyMesh& map = *mapPtr;
641 
642  // Update fields. No inflation, parallel sync.
643  mesh_.updateMesh(map);
644 
645  // Map patch fields using stored boundary fields. Note: assumes order
646  // of fields has not changed in object registry!
647  mapBoundaryFields<scalar, surfaceMesh>(map, sFlds);
648  mapBoundaryFields<vector, surfaceMesh>(map, vFlds);
649  mapBoundaryFields<sphericalTensor, surfaceMesh>(map, sptFlds);
650  mapBoundaryFields<symmTensor, surfaceMesh>(map, sytFlds);
651  mapBoundaryFields<tensor, surfaceMesh>(map, tFlds);
652 
653 
654  // Move mesh (since morphing does not do this)
655  if (map.hasMotionPoints())
656  {
657  mesh_.movePoints(map.preMotionPoints());
658  }
659 
660  // Adapt constructMaps.
661 
662  if (debug)
663  {
664  label index = map.reverseFaceMap().find(-1);
665 
666  if (index != -1)
667  {
669  << "reverseFaceMap contains -1 at index:"
670  << index << endl
671  << "This means that the repatch operation was not just"
672  << " a shuffle?" << abort(FatalError);
673  }
674  }
675 
676  forAll(constructFaceMap, proci)
677  {
678  inplaceRenumberWithFlip
679  (
680  map.reverseFaceMap(),
681  false,
682  true,
683  constructFaceMap[proci]
684  );
685  }
686 
687  return mapPtr;
688 }
689 
690 
691 // Detect shared points. Need processor patches to be present.
692 // Background: when adding bits of mesh one can get points which
693 // share the same position but are only detectable to be topologically
694 // the same point when doing parallel analysis. This routine will
695 // merge those points.
696 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
697 (
698  const labelList& pointToGlobalMaster,
699  labelListList& constructPointMap
700 )
701 {
702  // Find out which sets of points get merged and create a map from
703  // mesh point to unique point.
704 
705  label nShared = 0;
706  forAll(pointToGlobalMaster, pointi)
707  {
708  if (pointToGlobalMaster[pointi] != -1)
709  {
710  nShared++;
711  }
712  }
713 
714  Map<label> globalMasterToLocalMaster(2*nShared);
715  Map<label> pointToMaster(2*nShared);
716 
717  forAll(pointToGlobalMaster, pointi)
718  {
719  label globali = pointToGlobalMaster[pointi];
720  if (globali != -1)
721  {
722  const auto iter = globalMasterToLocalMaster.cfind(globali);
723 
724  if (iter.found())
725  {
726  pointToMaster.insert(pointi, *iter);
727  }
728  else
729  {
730  // Found first point. Designate as master
731  globalMasterToLocalMaster.insert(globali, pointi);
732  pointToMaster.insert(pointi, pointi);
733  }
734  }
735  }
736 
737  if (returnReduce(pointToMaster.size(), sumOp<label>()) == 0)
738  {
739  return nullptr;
740  }
741 
742 
743  polyTopoChange meshMod(mesh_);
744 
745  fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
746 
747  // Change the mesh (no inflation). Note: parallel comms allowed.
748  autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
749  mapPolyMesh& map = *mapPtr;
750 
751  // Update fields. No inflation, parallel sync.
752  mesh_.updateMesh(map);
753 
754  // Adapt constructMaps for merged points.
755  forAll(constructPointMap, proci)
756  {
757  labelList& constructMap = constructPointMap[proci];
758 
759  forAll(constructMap, i)
760  {
761  label oldPointi = constructMap[i];
762 
763  label newPointi = map.reversePointMap()[oldPointi];
764 
765  if (newPointi < -1)
766  {
767  constructMap[i] = -newPointi-2;
768  }
769  else if (newPointi >= 0)
770  {
771  constructMap[i] = newPointi;
772  }
773  else
774  {
776  << "Problem. oldPointi:" << oldPointi
777  << " newPointi:" << newPointi << abort(FatalError);
778  }
779  }
780  }
781 
782  return mapPtr;
783 }
784 
785 
786 void Foam::fvMeshDistribute::getCouplingData
787 (
788  const labelList& distribution,
789  labelList& sourceFace,
790  labelList& sourceProc,
791  labelList& sourcePatch,
792  labelList& sourceNewNbrProc,
793  labelList& sourcePointMaster
794 ) const
795 {
796  // Construct the coupling information for all (boundary) faces and
797  // points
798 
799  const label nBnd = mesh_.nBoundaryFaces();
800  sourceFace.setSize(nBnd);
801  sourceProc.setSize(nBnd);
802  sourcePatch.setSize(nBnd);
803  sourceNewNbrProc.setSize(nBnd);
804 
805  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
806 
807  // Get neighbouring meshFace labels and new processor of coupled boundaries.
808  labelList nbrFaces(nBnd, -1);
809  labelList nbrNewNbrProc(nBnd, -1);
810 
811  forAll(patches, patchi)
812  {
813  const polyPatch& pp = patches[patchi];
814 
815  if (pp.coupled())
816  {
817  label offset = pp.start() - mesh_.nInternalFaces();
818 
819  // Mesh labels of faces on this side
820  forAll(pp, i)
821  {
822  label bndI = offset + i;
823  nbrFaces[bndI] = pp.start()+i;
824  }
825 
826  // Which processor they will end up on
827  SubList<label>(nbrNewNbrProc, pp.size(), offset) =
828  labelUIndList(distribution, pp.faceCells())();
829  }
830  }
831 
832 
833  // Exchange the boundary data
834  syncTools::swapBoundaryFaceList(mesh_, nbrFaces);
835  syncTools::swapBoundaryFaceList(mesh_, nbrNewNbrProc);
836 
837 
838  forAll(patches, patchi)
839  {
840  const polyPatch& pp = patches[patchi];
841  label offset = pp.start() - mesh_.nInternalFaces();
842 
843  if (isA<processorPolyPatch>(pp))
844  {
845  const processorPolyPatch& procPatch =
846  refCast<const processorPolyPatch>(pp);
847 
848  // Check which of the two faces we store.
849 
850  if (procPatch.owner())
851  {
852  // Use my local face labels
853  forAll(pp, i)
854  {
855  label bndI = offset + i;
856  sourceFace[bndI] = pp.start()+i;
857  sourceProc[bndI] = Pstream::myProcNo();
858  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
859  }
860  }
861  else
862  {
863  // Use my neighbours face labels
864  forAll(pp, i)
865  {
866  label bndI = offset + i;
867  sourceFace[bndI] = nbrFaces[bndI];
868  sourceProc[bndI] = procPatch.neighbProcNo();
869  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
870  }
871  }
872 
873 
874  label patchi = -1;
875  if (isA<processorCyclicPolyPatch>(pp))
876  {
877  patchi = refCast<const processorCyclicPolyPatch>
878  (
879  pp
880  ).referPatchID();
881  }
882 
883  forAll(pp, i)
884  {
885  label bndI = offset + i;
886  sourcePatch[bndI] = patchi;
887  }
888  }
889  else if (isA<cyclicPolyPatch>(pp))
890  {
891  const cyclicPolyPatch& cpp = refCast<const cyclicPolyPatch>(pp);
892 
893  if (cpp.owner())
894  {
895  forAll(pp, i)
896  {
897  label bndI = offset + i;
898  sourceFace[bndI] = pp.start()+i;
899  sourceProc[bndI] = Pstream::myProcNo();
900  sourcePatch[bndI] = patchi;
901  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
902  }
903  }
904  else
905  {
906  forAll(pp, i)
907  {
908  label bndI = offset + i;
909  sourceFace[bndI] = nbrFaces[bndI];
910  sourceProc[bndI] = Pstream::myProcNo();
911  sourcePatch[bndI] = patchi;
912  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
913  }
914  }
915  }
916  else
917  {
918  // Normal (physical) boundary
919  forAll(pp, i)
920  {
921  label bndI = offset + i;
922  sourceFace[bndI] = -1;
923  sourceProc[bndI] = -1;
924  sourcePatch[bndI] = patchi;
925  sourceNewNbrProc[bndI] = -1;
926  }
927  }
928  }
929 
930 
931  // Collect coupled (collocated) points
932  sourcePointMaster.setSize(mesh_.nPoints());
933  sourcePointMaster = -1;
934  {
935  // Assign global master point
936  const globalIndex globalPoints(mesh_.nPoints());
937 
938  const globalMeshData& gmd = mesh_.globalData();
939  const indirectPrimitivePatch& cpp = gmd.coupledPatch();
940  const labelList& meshPoints = cpp.meshPoints();
941  const mapDistribute& slavesMap = gmd.globalCoPointSlavesMap();
942  const labelListList& slaves = gmd.globalCoPointSlaves();
943 
944  labelList elems(slavesMap.constructSize(), -1);
945  forAll(meshPoints, pointi)
946  {
947  const labelList& slots = slaves[pointi];
948 
949  if (slots.size())
950  {
951  // pointi is a master. Assign a unique label.
952 
953  label globalPointi = globalPoints.toGlobal(meshPoints[pointi]);
954  elems[pointi] = globalPointi;
955  forAll(slots, i)
956  {
957  label sloti = slots[i];
958  if (sloti >= meshPoints.size())
959  {
960  // Filter out local collocated points. We don't want
961  // to merge these
962  elems[slots[i]] = globalPointi;
963  }
964  }
965  }
966  }
967 
968  // Push slave-slot data back to slaves
969  slavesMap.reverseDistribute(elems.size(), elems, false);
970 
971  // Extract back onto mesh
972  forAll(meshPoints, pointi)
973  {
974  sourcePointMaster[meshPoints[pointi]] = elems[pointi];
975  }
976  }
977 }
978 
979 
980 // Subset the neighbourCell/neighbourProc fields
981 void Foam::fvMeshDistribute::subsetCouplingData
982 (
983  const fvMesh& mesh,
984  const labelList& pointMap,
985  const labelList& faceMap,
986  const labelList& cellMap,
987 
988  const labelList& oldDistribution,
989  const labelList& oldFaceOwner,
990  const labelList& oldFaceNeighbour,
991  const label oldInternalFaces,
992 
993  const labelList& sourceFace,
994  const labelList& sourceProc,
995  const labelList& sourcePatch,
996  const labelList& sourceNewNbrProc,
997  const labelList& sourcePointMaster,
998 
999  labelList& subFace,
1000  labelList& subProc,
1001  labelList& subPatch,
1002  labelList& subNewNbrProc,
1003  labelList& subPointMaster
1004 )
1005 {
1006  subFace.setSize(mesh.nBoundaryFaces());
1007  subProc.setSize(mesh.nBoundaryFaces());
1008  subPatch.setSize(mesh.nBoundaryFaces());
1009  subNewNbrProc.setSize(mesh.nBoundaryFaces());
1010 
1011  forAll(subFace, newBFacei)
1012  {
1013  label newFacei = newBFacei + mesh.nInternalFaces();
1014 
1015  label oldFacei = faceMap[newFacei];
1016 
1017  // Was oldFacei internal face? If so which side did we get.
1018  if (oldFacei < oldInternalFaces)
1019  {
1020  subFace[newBFacei] = oldFacei;
1021  subProc[newBFacei] = Pstream::myProcNo();
1022  subPatch[newBFacei] = -1;
1023 
1024  label oldOwn = oldFaceOwner[oldFacei];
1025  label oldNei = oldFaceNeighbour[oldFacei];
1026 
1027  if (oldOwn == cellMap[mesh.faceOwner()[newFacei]])
1028  {
1029  // We kept the owner side. Where does the neighbour move to?
1030  subNewNbrProc[newBFacei] = oldDistribution[oldNei];
1031  }
1032  else
1033  {
1034  // We kept the neighbour side.
1035  subNewNbrProc[newBFacei] = oldDistribution[oldOwn];
1036  }
1037  }
1038  else
1039  {
1040  // Was boundary face. Take over boundary information
1041  label oldBFacei = oldFacei - oldInternalFaces;
1042 
1043  subFace[newBFacei] = sourceFace[oldBFacei];
1044  subProc[newBFacei] = sourceProc[oldBFacei];
1045  subPatch[newBFacei] = sourcePatch[oldBFacei];
1046  subNewNbrProc[newBFacei] = sourceNewNbrProc[oldBFacei];
1047  }
1048  }
1049 
1050 
1051  subPointMaster = UIndirectList<label>(sourcePointMaster, pointMap);
1052 }
1053 
1054 
1055 // Find cells on mesh whose faceID/procID match the neighbour cell/proc of
1056 // domainMesh. Store the matching face.
1057 void Foam::fvMeshDistribute::findCouples
1058 (
1059  const primitiveMesh& mesh,
1060  const labelList& sourceFace,
1061  const labelList& sourceProc,
1062  const labelList& sourcePatch,
1063 
1064  const label domain,
1065  const primitiveMesh& domainMesh,
1066  const labelList& domainFace,
1067  const labelList& domainProc,
1068  const labelList& domainPatch,
1069 
1070  labelList& masterCoupledFaces,
1071  labelList& slaveCoupledFaces
1072 )
1073 {
1074  // Store domain neighbour as map so we can easily look for pair
1075  // with same face+proc.
1076  labelPairLookup map(domainFace.size());
1077 
1078  forAll(domainProc, bFacei)
1079  {
1080  if (domainProc[bFacei] != -1 && domainPatch[bFacei] == -1)
1081  {
1082  map.insert
1083  (
1084  labelPair(domainFace[bFacei], domainProc[bFacei]),
1085  bFacei
1086  );
1087  }
1088  }
1089 
1090 
1091  // Try to match mesh data.
1092 
1093  masterCoupledFaces.setSize(domainFace.size());
1094  slaveCoupledFaces.setSize(domainFace.size());
1095  label coupledI = 0;
1096 
1097  forAll(sourceFace, bFacei)
1098  {
1099  if (sourceProc[bFacei] != -1 && sourcePatch[bFacei] == -1)
1100  {
1101  labelPair myData(sourceFace[bFacei], sourceProc[bFacei]);
1102 
1103  const auto iter = map.cfind(myData);
1104 
1105  if (iter.found())
1106  {
1107  label nbrBFacei = *iter;
1108 
1109  masterCoupledFaces[coupledI] = mesh.nInternalFaces() + bFacei;
1110  slaveCoupledFaces[coupledI] =
1111  domainMesh.nInternalFaces()
1112  + nbrBFacei;
1113 
1114  coupledI++;
1115  }
1116  }
1117  }
1118 
1119  masterCoupledFaces.setSize(coupledI);
1120  slaveCoupledFaces.setSize(coupledI);
1121 
1122  if (debug)
1123  {
1124  Pout<< "findCouples : found " << coupledI
1125  << " faces that will be stitched" << nl << endl;
1126  }
1127 }
1128 
1129 
1130 // Map data on boundary faces to new mesh (resulting from adding two meshes)
1131 Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
1132 (
1133  const primitiveMesh& mesh, // mesh after adding
1134  const mapAddedPolyMesh& map,
1135  const labelList& boundaryData0, // on mesh before adding
1136  const label nInternalFaces1,
1137  const labelList& boundaryData1 // on added mesh
1138 )
1139 {
1140  labelList newBoundaryData(mesh.nBoundaryFaces());
1141 
1142  forAll(boundaryData0, oldBFacei)
1143  {
1144  label newFacei = map.oldFaceMap()[oldBFacei + map.nOldInternalFaces()];
1145 
1146  // Face still exists (is necessary?) and still boundary face
1147  if (newFacei >= 0 && newFacei >= mesh.nInternalFaces())
1148  {
1149  newBoundaryData[newFacei - mesh.nInternalFaces()] =
1150  boundaryData0[oldBFacei];
1151  }
1152  }
1153 
1154  forAll(boundaryData1, addedBFacei)
1155  {
1156  label newFacei = map.addedFaceMap()[addedBFacei + nInternalFaces1];
1157 
1158  if (newFacei >= 0 && newFacei >= mesh.nInternalFaces())
1159  {
1160  newBoundaryData[newFacei - mesh.nInternalFaces()] =
1161  boundaryData1[addedBFacei];
1162  }
1163  }
1164 
1165  return newBoundaryData;
1166 }
1167 
1168 
1169 Foam::labelList Foam::fvMeshDistribute::mapPointData
1170 (
1171  const primitiveMesh& mesh, // mesh after adding
1172  const mapAddedPolyMesh& map,
1173  const labelList& boundaryData0, // on mesh before adding
1174  const labelList& boundaryData1 // on added mesh
1175 )
1176 {
1177  labelList newBoundaryData(mesh.nPoints());
1178 
1179  forAll(boundaryData0, oldPointi)
1180  {
1181  label newPointi = map.oldPointMap()[oldPointi];
1182 
1183  // Point still exists (is necessary?)
1184  if (newPointi >= 0)
1185  {
1186  newBoundaryData[newPointi] = boundaryData0[oldPointi];
1187  }
1188  }
1189 
1190  forAll(boundaryData1, addedPointi)
1191  {
1192  label newPointi = map.addedPointMap()[addedPointi];
1193 
1194  if (newPointi >= 0)
1195  {
1196  newBoundaryData[newPointi] = boundaryData1[addedPointi];
1197  }
1198  }
1199 
1200  return newBoundaryData;
1201 }
1202 
1203 
1204 // Remove cells. Add all exposed faces to patch oldInternalPatchi
1205 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
1206 (
1207  const labelList& cellsToRemove,
1208  const label oldInternalPatchi
1209 )
1210 {
1211  // Mesh change engine
1212  polyTopoChange meshMod(mesh_);
1213 
1214  // Cell removal topo engine. Do NOT synchronize parallel since
1215  // we are doing a local cell removal.
1216  removeCells cellRemover(mesh_, false);
1217 
1218  // Get all exposed faces
1219  labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
1220 
1221  // Insert the topo changes
1222  cellRemover.setRefinement
1223  (
1224  cellsToRemove,
1225  exposedFaces,
1226  labelList(exposedFaces.size(), oldInternalPatchi), // patch for exposed
1227  // faces.
1228  meshMod
1229  );
1230 
1231 
1233  //tmp<surfaceScalarField> sfld(generateTestField(mesh_));
1234 
1235  // Save internal fields (note: not as DimensionedFields since would
1236  // get mapped)
1237  PtrList<Field<scalar>> sFlds;
1238  saveInternalFields(sFlds);
1239  PtrList<Field<vector>> vFlds;
1240  saveInternalFields(vFlds);
1241  PtrList<Field<sphericalTensor>> sptFlds;
1242  saveInternalFields(sptFlds);
1243  PtrList<Field<symmTensor>> sytFlds;
1244  saveInternalFields(sytFlds);
1245  PtrList<Field<tensor>> tFlds;
1246  saveInternalFields(tFlds);
1247 
1248  // Change the mesh. No inflation. Note: no parallel comms allowed.
1249  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
1250 
1251  // Update fields
1252  mesh_.updateMesh(map());
1253 
1254 
1255  // Any exposed faces in a surfaceField will not be mapped. Map the value
1256  // of these separately (until there is support in all PatchFields for
1257  // mapping from internal faces ...)
1258 
1259  mapExposedFaces(map(), sFlds);
1260  mapExposedFaces(map(), vFlds);
1261  mapExposedFaces(map(), sptFlds);
1262  mapExposedFaces(map(), sytFlds);
1263  mapExposedFaces(map(), tFlds);
1264 
1265 
1267  //testField(sfld);
1268 
1269 
1270  // Move mesh (since morphing does not do this)
1271  if (map().hasMotionPoints())
1272  {
1273  mesh_.movePoints(map().preMotionPoints());
1274  }
1275 
1276 
1277  return map;
1278 }
1279 
1280 
1281 // Delete and add processor patches. Changes mesh and returns per neighbour proc
1282 // the processor patchID.
1283 void Foam::fvMeshDistribute::addProcPatches
1284 (
1285  const labelList& nbrProc, // processor that neighbour is now on
1286  const labelList& referPatchID, // patchID (or -1) I originated from
1287  List<Map<label>>& procPatchID
1288 )
1289 {
1290  // Now use the neighbourFace/Proc to repatch the mesh. These lists
1291  // contain for all current boundary faces the global patchID (for non-proc
1292  // patch) or the processor.
1293 
1294  // Determine a visit order such that the processor patches get added
1295  // in order of increasing neighbour processor (and for same neighbour
1296  // processor (in case of processor cyclics) in order of increasing
1297  // 'refer' patch)
1298  labelList indices;
1299  sortedOrder(nbrProc, indices, lessProcPatches(nbrProc, referPatchID));
1300 
1301  procPatchID.setSize(Pstream::nProcs());
1302 
1303  forAll(indices, i)
1304  {
1305  label bFacei = indices[i];
1306  label proci = nbrProc[bFacei];
1307 
1308  if (proci != -1 && proci != Pstream::myProcNo())
1309  {
1310  if (!procPatchID[proci].found(referPatchID[bFacei]))
1311  {
1312  // No patch for neighbour yet. Is either a normal processor
1313  // patch or a processorCyclic patch.
1314 
1315  if (referPatchID[bFacei] == -1)
1316  {
1317  // Ordinary processor boundary
1318 
1319  processorPolyPatch pp
1320  (
1321  0, // size
1322  mesh_.nFaces(),
1323  mesh_.boundaryMesh().size(),
1324  mesh_.boundaryMesh(),
1326  proci
1327  );
1328 
1329  procPatchID[proci].insert
1330  (
1331  referPatchID[bFacei],
1333  (
1334  mesh_,
1335  pp,
1336  dictionary(), // optional per field patchField
1337  processorFvPatchField<scalar>::typeName,
1338  false // not parallel sync
1339  )
1340  );
1341  }
1342  else
1343  {
1344  const coupledPolyPatch& pcPatch
1345  = refCast<const coupledPolyPatch>
1346  (
1347  mesh_.boundaryMesh()[referPatchID[bFacei]]
1348  );
1349  processorCyclicPolyPatch pp
1350  (
1351  0, // size
1352  mesh_.nFaces(),
1353  mesh_.boundaryMesh().size(),
1354  mesh_.boundaryMesh(),
1356  proci,
1357  pcPatch.name(),
1358  pcPatch.transform()
1359  );
1360 
1361  procPatchID[proci].insert
1362  (
1363  referPatchID[bFacei],
1365  (
1366  mesh_,
1367  pp,
1368  dictionary(), // optional per field patchField
1369  processorCyclicFvPatchField<scalar>::typeName,
1370  false // not parallel sync
1371  )
1372  );
1373  }
1374  }
1375  }
1376  }
1377 }
1378 
1379 
1380 // Get boundary faces to be repatched. Is -1 or new patchID
1381 Foam::labelList Foam::fvMeshDistribute::getBoundaryPatch
1382 (
1383  const labelList& nbrProc, // new processor per boundary face
1384  const labelList& referPatchID, // patchID (or -1) I originated from
1385  const List<Map<label>>& procPatchID // per proc the new procPatches
1386 )
1387 {
1388  labelList patchIDs(nbrProc);
1389 
1390  forAll(nbrProc, bFacei)
1391  {
1392  if (nbrProc[bFacei] == Pstream::myProcNo())
1393  {
1394  label origPatchi = referPatchID[bFacei];
1395  patchIDs[bFacei] = origPatchi;
1396  }
1397  else if (nbrProc[bFacei] != -1)
1398  {
1399  label origPatchi = referPatchID[bFacei];
1400  patchIDs[bFacei] = procPatchID[nbrProc[bFacei]][origPatchi];
1401  }
1402  else
1403  {
1404  patchIDs[bFacei] = -1;
1405  }
1406  }
1407  return patchIDs;
1408 }
1409 
1410 
1411 // Send mesh and coupling data.
1412 void Foam::fvMeshDistribute::sendMesh
1413 (
1414  const label domain,
1415  const fvMesh& mesh,
1416 
1417  const wordList& pointZoneNames,
1418  const wordList& faceZoneNames,
1419  const wordList& cellZoneNames,
1420 
1421  const labelList& sourceFace,
1422  const labelList& sourceProc,
1423  const labelList& sourcePatch,
1424  const labelList& sourceNewNbrProc,
1425  const labelList& sourcePointMaster,
1426  Ostream& toDomain
1427 )
1428 {
1429  if (debug)
1430  {
1431  Pout<< "Sending to domain " << domain << nl
1432  << " nPoints:" << mesh.nPoints() << nl
1433  << " nFaces:" << mesh.nFaces() << nl
1434  << " nCells:" << mesh.nCells() << nl
1435  << " nPatches:" << mesh.boundaryMesh().size() << nl
1436  << endl;
1437  }
1438 
1439  // Assume sparse, possibly overlapping point zones. Get contents
1440  // in merged-zone indices.
1441  CompactListList<label> zonePoints;
1442  {
1443  const pointZoneMesh& pointZones = mesh.pointZones();
1444 
1445  labelList rowSizes(pointZoneNames.size(), Zero);
1446 
1447  forAll(pointZoneNames, nameI)
1448  {
1449  label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1450 
1451  if (myZoneID != -1)
1452  {
1453  rowSizes[nameI] = pointZones[myZoneID].size();
1454  }
1455  }
1456  zonePoints.setSize(rowSizes);
1457 
1458  forAll(pointZoneNames, nameI)
1459  {
1460  label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1461 
1462  if (myZoneID != -1)
1463  {
1464  zonePoints[nameI].deepCopy(pointZones[myZoneID]);
1465  }
1466  }
1467  }
1468 
1469  // Assume sparse, possibly overlapping face zones
1470  CompactListList<label> zoneFaces;
1471  CompactListList<bool> zoneFaceFlip;
1472  {
1473  const faceZoneMesh& faceZones = mesh.faceZones();
1474 
1475  labelList rowSizes(faceZoneNames.size(), Zero);
1476 
1477  forAll(faceZoneNames, nameI)
1478  {
1479  label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1480 
1481  if (myZoneID != -1)
1482  {
1483  rowSizes[nameI] = faceZones[myZoneID].size();
1484  }
1485  }
1486 
1487  zoneFaces.setSize(rowSizes);
1488  zoneFaceFlip.setSize(rowSizes);
1489 
1490  forAll(faceZoneNames, nameI)
1491  {
1492  label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1493 
1494  if (myZoneID != -1)
1495  {
1496  zoneFaces[nameI].deepCopy(faceZones[myZoneID]);
1497  zoneFaceFlip[nameI].deepCopy(faceZones[myZoneID].flipMap());
1498  }
1499  }
1500  }
1501 
1502  // Assume sparse, possibly overlapping cell zones
1503  CompactListList<label> zoneCells;
1504  {
1505  const cellZoneMesh& cellZones = mesh.cellZones();
1506 
1507  labelList rowSizes(cellZoneNames.size(), Zero);
1508 
1509  forAll(cellZoneNames, nameI)
1510  {
1511  label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1512 
1513  if (myZoneID != -1)
1514  {
1515  rowSizes[nameI] = cellZones[myZoneID].size();
1516  }
1517  }
1518 
1519  zoneCells.setSize(rowSizes);
1520 
1521  forAll(cellZoneNames, nameI)
1522  {
1523  label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1524 
1525  if (myZoneID != -1)
1526  {
1527  zoneCells[nameI].deepCopy(cellZones[myZoneID]);
1528  }
1529  }
1530  }
1532  //labelList cellZoneID;
1533  //if (hasCellZones)
1534  //{
1535  // cellZoneID.setSize(mesh.nCells());
1536  // cellZoneID = -1;
1537  //
1538  // const cellZoneMesh& cellZones = mesh.cellZones();
1539  //
1540  // forAll(cellZones, zoneI)
1541  // {
1542  // labelUIndList(cellZoneID, cellZones[zoneI]) = zoneI;
1543  // }
1544  //}
1545 
1546  // Send
1547  toDomain
1548  << mesh.points()
1549  << CompactListList<label, face>(mesh.faces())
1550  << mesh.faceOwner()
1551  << mesh.faceNeighbour()
1552  << mesh.boundaryMesh()
1553 
1554  << zonePoints
1555  << zoneFaces
1556  << zoneFaceFlip
1557  << zoneCells
1558 
1559  << sourceFace
1560  << sourceProc
1561  << sourcePatch
1562  << sourceNewNbrProc
1563  << sourcePointMaster;
1564 
1565 
1566  if (debug)
1567  {
1568  Pout<< "Started sending mesh to domain " << domain
1569  << endl;
1570  }
1571 }
1572 
1573 
1574 // Receive mesh. Opposite of sendMesh
1575 Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
1576 (
1577  const label domain,
1578  const wordList& pointZoneNames,
1579  const wordList& faceZoneNames,
1580  const wordList& cellZoneNames,
1581  const Time& runTime,
1582  labelList& domainSourceFace,
1583  labelList& domainSourceProc,
1584  labelList& domainSourcePatch,
1585  labelList& domainSourceNewNbrProc,
1586  labelList& domainSourcePointMaster,
1587  Istream& fromNbr
1588 )
1589 {
1590  pointField domainPoints(fromNbr);
1591  faceList domainFaces = CompactListList<label, face>(fromNbr)();
1592  labelList domainAllOwner(fromNbr);
1593  labelList domainAllNeighbour(fromNbr);
1594  PtrList<entry> patchEntries(fromNbr);
1595 
1596  CompactListList<label> zonePoints(fromNbr);
1597  CompactListList<label> zoneFaces(fromNbr);
1598  CompactListList<bool> zoneFaceFlip(fromNbr);
1599  CompactListList<label> zoneCells(fromNbr);
1600 
1601  fromNbr
1602  >> domainSourceFace
1603  >> domainSourceProc
1604  >> domainSourcePatch
1605  >> domainSourceNewNbrProc
1606  >> domainSourcePointMaster;
1607 
1608  // Construct fvMesh
1609  auto domainMeshPtr = autoPtr<fvMesh>::New
1610  (
1611  IOobject
1612  (
1614  runTime.timeName(),
1615  runTime,
1617  ),
1618  std::move(domainPoints),
1619  std::move(domainFaces),
1620  std::move(domainAllOwner),
1621  std::move(domainAllNeighbour),
1622  false // no parallel comms
1623  );
1624  fvMesh& domainMesh = *domainMeshPtr;
1625 
1626  List<polyPatch*> patches(patchEntries.size());
1627 
1628  forAll(patchEntries, patchi)
1629  {
1630  patches[patchi] = polyPatch::New
1631  (
1632  patchEntries[patchi].keyword(),
1633  patchEntries[patchi].dict(),
1634  patchi,
1635  domainMesh.boundaryMesh()
1636  ).ptr();
1637  }
1638  // Add patches; no parallel comms
1639  domainMesh.addFvPatches(patches, false);
1640 
1641  // Construct zones
1642  List<pointZone*> pZonePtrs(pointZoneNames.size());
1643  forAll(pZonePtrs, i)
1644  {
1645  pZonePtrs[i] = new pointZone
1646  (
1647  pointZoneNames[i],
1648  zonePoints[i],
1649  i,
1650  domainMesh.pointZones()
1651  );
1652  }
1653 
1654  List<faceZone*> fZonePtrs(faceZoneNames.size());
1655  forAll(fZonePtrs, i)
1656  {
1657  fZonePtrs[i] = new faceZone
1658  (
1659  faceZoneNames[i],
1660  zoneFaces[i],
1661  zoneFaceFlip[i],
1662  i,
1663  domainMesh.faceZones()
1664  );
1665  }
1666 
1667  List<cellZone*> cZonePtrs(cellZoneNames.size());
1668  forAll(cZonePtrs, i)
1669  {
1670  cZonePtrs[i] = new cellZone
1671  (
1672  cellZoneNames[i],
1673  zoneCells[i],
1674  i,
1675  domainMesh.cellZones()
1676  );
1677  }
1678  domainMesh.addZones(pZonePtrs, fZonePtrs, cZonePtrs);
1679 
1680  return domainMeshPtr;
1681 }
1682 
1683 
1684 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1685 
1686 Foam::fvMeshDistribute::fvMeshDistribute(fvMesh& mesh, const scalar mergeTol)
1687 :
1688  mesh_(mesh),
1689  mergeTol_(mergeTol)
1690 {}
1691 
1692 
1693 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1694 
1697  const labelList& distribution
1698 )
1699 {
1700  labelList nCells(Pstream::nProcs(), Zero);
1701  forAll(distribution, celli)
1702  {
1703  label newProc = distribution[celli];
1704 
1705  if (newProc < 0 || newProc >= Pstream::nProcs())
1706  {
1708  << "Distribution should be in range 0.." << Pstream::nProcs()-1
1709  << endl
1710  << "At index " << celli << " distribution:" << newProc
1711  << abort(FatalError);
1712  }
1713  nCells[newProc]++;
1714  }
1715  return nCells;
1716 }
1717 
1718 
1721  const labelList& distribution
1722 )
1723 {
1724  // Some checks on distribution
1725  if (distribution.size() != mesh_.nCells())
1726  {
1728  << "Size of distribution:"
1729  << distribution.size() << " mesh nCells:" << mesh_.nCells()
1730  << abort(FatalError);
1731  }
1732 
1733 
1734  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1735 
1736  // Check all processors have same non-proc patches in same order.
1737  if (patches.checkParallelSync(true))
1738  {
1740  << "This application requires all non-processor patches"
1741  << " to be present in the same order on all patches" << nl
1742  << "followed by the processor patches (which of course are unique)."
1743  << nl
1744  << "Local patches:" << mesh_.boundaryMesh().names()
1745  << abort(FatalError);
1746  }
1747 
1748  // Save some data for mapping later on
1749  const label nOldPoints(mesh_.nPoints());
1750  const label nOldFaces(mesh_.nFaces());
1751  const label nOldCells(mesh_.nCells());
1752  labelList oldPatchStarts(patches.size());
1753  labelList oldPatchNMeshPoints(patches.size());
1754  forAll(patches, patchi)
1755  {
1756  oldPatchStarts[patchi] = patches[patchi].start();
1757  oldPatchNMeshPoints[patchi] = patches[patchi].nPoints();
1758  }
1759 
1760 
1761 
1762  // Short circuit trivial case.
1763  if (!Pstream::parRun())
1764  {
1765  // Collect all maps and return
1767  (
1768  mesh_,
1769 
1770  nOldPoints,
1771  nOldFaces,
1772  nOldCells,
1773  std::move(oldPatchStarts),
1774  std::move(oldPatchNMeshPoints),
1775 
1776  labelListList(one(), identity(mesh_.nPoints())), //subPointMap
1777  labelListList(one(), identity(mesh_.nFaces())), //subFaceMap
1778  labelListList(one(), identity(mesh_.nCells())), //subCellMap
1779  labelListList(one(), identity(patches.size())), //subPatchMap
1780 
1781  labelListList(one(), identity(mesh_.nPoints())), //pointMap
1782  labelListList(one(), identity(mesh_.nFaces())), //faceMap
1783  labelListList(one(), identity(mesh_.nCells())), //cellMap
1784  labelListList(one(), identity(patches.size())) //patchMap
1785  );
1786  }
1787 
1788 
1789  // Collect any zone names
1790  const wordList pointZoneNames(mergeWordList(mesh_.pointZones().names()));
1791  const wordList faceZoneNames(mergeWordList(mesh_.faceZones().names()));
1792  const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
1793 
1794 
1795 
1796  // Local environment of all boundary faces
1797  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1798 
1799  // A face is uniquely defined by
1800  // - proc
1801  // - local face no
1802  //
1803  // To glue the parts of meshes which can get sent from anywhere we
1804  // need to know on boundary faces what the above tuple on both sides is.
1805  // So we need to maintain:
1806  // - original face
1807  // - original processor id (= trivial)
1808  // For coupled boundaries (where the faces are 'duplicate') we take the
1809  // lowest numbered processor as the data to store.
1810  //
1811  // Additionally to create the procboundaries we need to know where the owner
1812  // cell on the other side now is: newNeighbourProc.
1813  //
1814 
1815  // physical boundary:
1816  // sourceProc = -1
1817  // sourceNewNbrProc = -1
1818  // sourceFace = -1
1819  // sourcePatch = patchID
1820  // processor boundary:
1821  // sourceProc = proc (on owner side)
1822  // sourceNewNbrProc = distribution of coupled cell
1823  // sourceFace = face (on owner side)
1824  // sourcePatch = -1
1825  // ?cyclic:
1826  // ? sourceProc = proc
1827  // ? sourceNewNbrProc = distribution of coupled cell
1828  // ? sourceFace = face (on owner side)
1829  // ? sourcePatch = patchID
1830  // processor-cyclic boundary:
1831  // sourceProc = proc (on owner side)
1832  // sourceNewNbrProc = distribution of coupled cell
1833  // sourceFace = face (on owner side)
1834  // sourcePatch = patchID
1835 
1836  labelList sourcePatch;
1837  labelList sourceFace;
1838  labelList sourceProc;
1839  labelList sourceNewNbrProc;
1840  labelList sourcePointMaster;
1841  getCouplingData
1842  (
1843  distribution,
1844  sourceFace,
1845  sourceProc,
1846  sourcePatch,
1847  sourceNewNbrProc,
1848  sourcePointMaster
1849  );
1850 
1851 
1852  // Remove meshPhi. Since this would otherwise disappear anyway
1853  // during topo changes and we have to guarantee that all the fields
1854  // can be sent.
1855  mesh_.clearOut();
1856  mesh_.resetMotion();
1857 
1858  // Get data to send. Make sure is synchronised
1859 
1860  HashTable<wordList> allFieldNames;
1861 
1862  getFieldNames<volScalarField>(mesh_, allFieldNames);
1863  getFieldNames<volVectorField>(mesh_, allFieldNames);
1864  getFieldNames<volSphericalTensorField>(mesh_, allFieldNames);
1865  getFieldNames<volSymmTensorField>(mesh_, allFieldNames);
1866  getFieldNames<volTensorField>(mesh_, allFieldNames);
1867 
1868  getFieldNames<surfaceScalarField>(mesh_, allFieldNames);
1869  getFieldNames<surfaceVectorField>(mesh_, allFieldNames);
1870  getFieldNames<surfaceSphericalTensorField>(mesh_, allFieldNames);
1871  getFieldNames<surfaceSymmTensorField>(mesh_, allFieldNames);
1872  getFieldNames<surfaceTensorField>(mesh_, allFieldNames);
1873 
1874  getFieldNames<volScalarField::Internal>(mesh_, allFieldNames);
1875  getFieldNames<volVectorField::Internal>(mesh_, allFieldNames);
1876  getFieldNames<volSphericalTensorField::Internal>(mesh_, allFieldNames);
1877  getFieldNames<volSymmTensorField::Internal>(mesh_, allFieldNames);
1878  getFieldNames<volTensorField::Internal>(mesh_, allFieldNames);
1879 
1880 
1881  // Find patch to temporarily put exposed and processor faces into.
1882  const label oldInternalPatchi = findNonEmptyPatch();
1883 
1884 
1885  // Delete processor patches, starting from the back. Move all faces into
1886  // oldInternalPatchi.
1887  labelList repatchFaceMap;
1888  {
1889  autoPtr<mapPolyMesh> repatchMap = deleteProcPatches(oldInternalPatchi);
1890 
1891  // Store face map (only face ordering that changed)
1892  repatchFaceMap = repatchMap().faceMap();
1893 
1894  // Reorder all boundary face data (sourceProc, sourceFace etc.)
1895  labelList bFaceMap
1896  (
1898  (
1899  repatchMap().reverseFaceMap(),
1900  mesh_.nBoundaryFaces(),
1901  mesh_.nInternalFaces()
1902  )
1903  - mesh_.nInternalFaces()
1904  );
1905 
1906  inplaceReorder(bFaceMap, sourceFace);
1907  inplaceReorder(bFaceMap, sourceProc);
1908  inplaceReorder(bFaceMap, sourcePatch);
1909  inplaceReorder(bFaceMap, sourceNewNbrProc);
1910  }
1911 
1912 
1913 
1914  // Print a bit.
1915  if (debug)
1916  {
1917  Pout<< nl << "MESH WITH PROC PATCHES DELETED:" << endl;
1918  printMeshInfo(mesh_);
1919  printFieldInfo<volScalarField>(mesh_);
1920  printFieldInfo<volVectorField>(mesh_);
1921  printFieldInfo<volSphericalTensorField>(mesh_);
1922  printFieldInfo<volSymmTensorField>(mesh_);
1923  printFieldInfo<volTensorField>(mesh_);
1924  printFieldInfo<surfaceScalarField>(mesh_);
1925  printFieldInfo<surfaceVectorField>(mesh_);
1926  printFieldInfo<surfaceSphericalTensorField>(mesh_);
1927  printFieldInfo<surfaceSymmTensorField>(mesh_);
1928  printFieldInfo<surfaceTensorField>(mesh_);
1929  Pout<< nl << endl;
1930  }
1931 
1932 
1933 
1934  // Maps from subsetted mesh (that is sent) back to original maps
1935  labelListList subCellMap(Pstream::nProcs());
1936  labelListList subFaceMap(Pstream::nProcs());
1937  labelListList subPointMap(Pstream::nProcs());
1938  labelListList subPatchMap(Pstream::nProcs());
1939  // Maps from subsetted mesh to reconstructed mesh
1940  labelListList constructCellMap(Pstream::nProcs());
1941  labelListList constructFaceMap(Pstream::nProcs());
1942  labelListList constructPointMap(Pstream::nProcs());
1943  labelListList constructPatchMap(Pstream::nProcs());
1944 
1945 
1946  // Find out schedule
1947  // ~~~~~~~~~~~~~~~~~
1948 
1949  labelList nSendCells(countCells(distribution));
1950  labelList nRevcCells(Pstream::nProcs());
1951  Pstream::allToAll(nSendCells, nRevcCells);
1952 
1953  // Allocate buffers
1955 
1956 
1957  // What to send to neighbouring domains
1958  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1959 
1960  // Disable parallel.
1961  const bool oldParRun = UPstream::parRun(false);
1962 
1963  forAll(nSendCells, recvProc)
1964  {
1965  if (recvProc != Pstream::myProcNo() && nSendCells[recvProc] > 0)
1966  {
1967  // Send to recvProc
1968 
1969  if (debug)
1970  {
1971  Pout<< nl
1972  << "SUBSETTING FOR DOMAIN " << recvProc
1973  << " cells to send:"
1974  << nSendCells[recvProc]
1975  << nl << endl;
1976  }
1977 
1978  // Pstream for sending mesh and fields
1979  //OPstream str(Pstream::commsTypes::blocking, recvProc);
1980  UOPstream str(recvProc, pBufs);
1981 
1982  // Mesh subsetting engine - subset the cells of the current domain.
1983  fvMeshSubset subsetter
1984  (
1985  mesh_,
1986  recvProc,
1987  distribution,
1988  oldInternalPatchi, // oldInternalFaces patch
1989  false // no parallel sync
1990  );
1991 
1992  subCellMap[recvProc] = subsetter.cellMap();
1993  subFaceMap[recvProc] = subsetter.faceFlipMap();
1994  inplaceRenumberWithFlip
1995  (
1996  repatchFaceMap,
1997  false, // oldToNew has flip
1998  true, // subFaceMap has flip
1999  subFaceMap[recvProc]
2000  );
2001  subPointMap[recvProc] = subsetter.pointMap();
2002  subPatchMap[recvProc] = subsetter.patchMap();
2003 
2004 
2005  // Subset the boundary fields (owner/neighbour/processor)
2006  labelList procSourceFace;
2007  labelList procSourceProc;
2008  labelList procSourcePatch;
2009  labelList procSourceNewNbrProc;
2010  labelList procSourcePointMaster;
2011 
2012  subsetCouplingData
2013  (
2014  subsetter.subMesh(),
2015  subsetter.pointMap(), // from subMesh to mesh
2016  subsetter.faceMap(), // ,, ,,
2017  subsetter.cellMap(), // ,, ,,
2018 
2019  distribution, // old mesh distribution
2020  mesh_.faceOwner(), // old owner
2021  mesh_.faceNeighbour(),
2022  mesh_.nInternalFaces(),
2023 
2024  sourceFace,
2025  sourceProc,
2026  sourcePatch,
2027  sourceNewNbrProc,
2028  sourcePointMaster,
2029 
2030  procSourceFace,
2031  procSourceProc,
2032  procSourcePatch,
2033  procSourceNewNbrProc,
2034  procSourcePointMaster
2035  );
2036 
2037 
2038  // Send to neighbour
2039  sendMesh
2040  (
2041  recvProc,
2042  subsetter.subMesh(),
2043 
2044  pointZoneNames,
2045  faceZoneNames,
2046  cellZoneNames,
2047 
2048  procSourceFace,
2049  procSourceProc,
2050  procSourcePatch,
2051  procSourceNewNbrProc,
2052  procSourcePointMaster,
2053 
2054  str
2055  );
2056 
2057  // volFields
2058  sendFields<volScalarField>
2059  (
2060  recvProc,
2061  allFieldNames,
2062  subsetter,
2063  str
2064  );
2065  sendFields<volVectorField>
2066  (
2067  recvProc,
2068  allFieldNames,
2069  subsetter,
2070  str
2071  );
2072  sendFields<volSphericalTensorField>
2073  (
2074  recvProc,
2075  allFieldNames,
2076  subsetter,
2077  str
2078  );
2079  sendFields<volSymmTensorField>
2080  (
2081  recvProc,
2082  allFieldNames,
2083  subsetter,
2084  str
2085  );
2086  sendFields<volTensorField>
2087  (
2088  recvProc,
2089  allFieldNames,
2090  subsetter,
2091  str
2092  );
2093 
2094  // surfaceFields
2095  sendFields<surfaceScalarField>
2096  (
2097  recvProc,
2098  allFieldNames,
2099  subsetter,
2100  str
2101  );
2102  sendFields<surfaceVectorField>
2103  (
2104  recvProc,
2105  allFieldNames,
2106  subsetter,
2107  str
2108  );
2109  sendFields<surfaceSphericalTensorField>
2110  (
2111  recvProc,
2112  allFieldNames,
2113  subsetter,
2114  str
2115  );
2116  sendFields<surfaceSymmTensorField>
2117  (
2118  recvProc,
2119  allFieldNames,
2120  subsetter,
2121  str
2122  );
2123  sendFields<surfaceTensorField>
2124  (
2125  recvProc,
2126  allFieldNames,
2127  subsetter,
2128  str
2129  );
2130 
2131  // Dimensioned fields
2132  sendFields<volScalarField::Internal>
2133  (
2134  recvProc,
2135  allFieldNames,
2136  subsetter,
2137  str
2138  );
2139  sendFields<volVectorField::Internal>
2140  (
2141  recvProc,
2142  allFieldNames,
2143  subsetter,
2144  str
2145  );
2146  sendFields<volSphericalTensorField::Internal>
2147  (
2148  recvProc,
2149  allFieldNames,
2150  subsetter,
2151  str
2152  );
2153  sendFields<volSymmTensorField::Internal>
2154  (
2155  recvProc,
2156  allFieldNames,
2157  subsetter,
2158  str
2159  );
2160  sendFields<volTensorField::Internal>
2161  (
2162  recvProc,
2163  allFieldNames,
2164  subsetter,
2165  str
2166  );
2167  }
2168  }
2169 
2170 
2171  UPstream::parRun(oldParRun); // Restore parallel state
2172 
2173 
2174  // Start sending&receiving from buffers
2175  pBufs.finishedSends();
2176 
2177 
2178  // Subset the part that stays
2179  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
2180 
2181  {
2182  // Save old mesh maps before changing mesh
2183  const labelList oldFaceOwner(mesh_.faceOwner());
2184  const labelList oldFaceNeighbour(mesh_.faceNeighbour());
2185  const label oldInternalFaces = mesh_.nInternalFaces();
2186 
2187  // Remove cells.
2188  autoPtr<mapPolyMesh> subMap
2189  (
2190  doRemoveCells
2191  (
2192  select(false, distribution, Pstream::myProcNo()),
2193  oldInternalPatchi
2194  )
2195  );
2196 
2197  // Addressing from subsetted mesh
2198  subCellMap[Pstream::myProcNo()] = subMap().cellMap();
2199  subFaceMap[Pstream::myProcNo()] = renumber
2200  (
2201  repatchFaceMap,
2202  subMap().faceMap()
2203  );
2204  // Insert the sign bit from face flipping
2205  labelList& faceMap = subFaceMap[Pstream::myProcNo()];
2206  forAll(faceMap, faceI)
2207  {
2208  faceMap[faceI] += 1;
2209  }
2210  const labelHashSet& flip = subMap().flipFaceFlux();
2211  for (const label facei : flip)
2212  {
2213  faceMap[facei] = -faceMap[facei];
2214  }
2215  subPointMap[Pstream::myProcNo()] = subMap().pointMap();
2216  subPatchMap[Pstream::myProcNo()] = identity(patches.size());
2217 
2218  // Initialize all addressing into current mesh
2219  constructCellMap[Pstream::myProcNo()] = identity(mesh_.nCells());
2220  constructFaceMap[Pstream::myProcNo()] = identity(mesh_.nFaces(), 1);
2221  constructPointMap[Pstream::myProcNo()] = identity(mesh_.nPoints());
2222  constructPatchMap[Pstream::myProcNo()] = identity(patches.size());
2223 
2224  // Subset the mesh data: neighbourCell/neighbourProc
2225  // fields
2226  labelList domainSourceFace;
2227  labelList domainSourceProc;
2228  labelList domainSourcePatch;
2229  labelList domainSourceNewNbrProc;
2230  labelList domainSourcePointMaster;
2231 
2232  subsetCouplingData
2233  (
2234  mesh_, // new mesh
2235  subMap().pointMap(), // from new to original mesh
2236  subMap().faceMap(), // from new to original mesh
2237  subMap().cellMap(),
2238 
2239  distribution, // distribution before subsetting
2240  oldFaceOwner, // owner before subsetting
2241  oldFaceNeighbour, // neighbour ,,
2242  oldInternalFaces, // nInternalFaces ,,
2243 
2244  sourceFace,
2245  sourceProc,
2246  sourcePatch,
2247  sourceNewNbrProc,
2248  sourcePointMaster,
2249 
2250  domainSourceFace,
2251  domainSourceProc,
2252  domainSourcePatch,
2253  domainSourceNewNbrProc,
2254  domainSourcePointMaster
2255  );
2256 
2257  sourceFace.transfer(domainSourceFace);
2258  sourceProc.transfer(domainSourceProc);
2259  sourcePatch.transfer(domainSourcePatch);
2260  sourceNewNbrProc.transfer(domainSourceNewNbrProc);
2261  sourcePointMaster.transfer(domainSourcePointMaster);
2262  }
2263 
2264 
2265  // Print a bit.
2266  if (debug)
2267  {
2268  Pout<< nl << "STARTING MESH:" << endl;
2269  printMeshInfo(mesh_);
2270  printFieldInfo<volScalarField>(mesh_);
2271  printFieldInfo<volVectorField>(mesh_);
2272  printFieldInfo<volSphericalTensorField>(mesh_);
2273  printFieldInfo<volSymmTensorField>(mesh_);
2274  printFieldInfo<volTensorField>(mesh_);
2275  printFieldInfo<surfaceScalarField>(mesh_);
2276  printFieldInfo<surfaceVectorField>(mesh_);
2277  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2278  printFieldInfo<surfaceSymmTensorField>(mesh_);
2279  printFieldInfo<surfaceTensorField>(mesh_);
2280  Pout<< nl << endl;
2281  }
2282 
2283 
2284 
2285  // Receive and add what was sent
2286  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2287 
2288  // Disable parallel. Original state already known.
2289  UPstream::parRun(false);
2290 
2291  forAll(nRevcCells, sendProc)
2292  {
2293  // Did processor sendProc send anything to me?
2294  if (sendProc != Pstream::myProcNo() && nRevcCells[sendProc] > 0)
2295  {
2296  if (debug)
2297  {
2298  Pout<< nl
2299  << "RECEIVING FROM DOMAIN " << sendProc
2300  << " cells to receive:"
2301  << nRevcCells[sendProc]
2302  << nl << endl;
2303  }
2304 
2305 
2306  // Pstream for receiving mesh and fields
2307  UIPstream str(sendProc, pBufs);
2308 
2309 
2310  // Receive from sendProc
2311  labelList domainSourceFace;
2312  labelList domainSourceProc;
2313  labelList domainSourcePatch;
2314  labelList domainSourceNewNbrProc;
2315  labelList domainSourcePointMaster;
2316 
2317  autoPtr<fvMesh> domainMeshPtr;
2318 
2324 
2330 
2336 
2337 
2338  // Opposite of sendMesh
2339  {
2340  domainMeshPtr = receiveMesh
2341  (
2342  sendProc,
2343  pointZoneNames,
2344  faceZoneNames,
2345  cellZoneNames,
2346 
2347  const_cast<Time&>(mesh_.time()),
2348  domainSourceFace,
2349  domainSourceProc,
2350  domainSourcePatch,
2351  domainSourceNewNbrProc,
2352  domainSourcePointMaster,
2353  str
2354  );
2355  fvMesh& domainMesh = domainMeshPtr();
2356  // Force construction of various on mesh.
2357  //(void)domainMesh.globalData();
2358 
2359 
2360  // Receive fields. Read as single dictionary because
2361  // of problems reading consecutive fields from single stream.
2362  dictionary fieldDicts(str);
2363 
2364  // Vol fields
2365  receiveFields<volScalarField>
2366  (
2367  sendProc,
2368  allFieldNames,
2369  domainMesh,
2370  vsf,
2371  fieldDicts
2372  );
2373  receiveFields<volVectorField>
2374  (
2375  sendProc,
2376  allFieldNames,
2377  domainMesh,
2378  vvf,
2379  fieldDicts
2380  );
2381  receiveFields<volSphericalTensorField>
2382  (
2383  sendProc,
2384  allFieldNames,
2385  domainMesh,
2386  vsptf,
2387  fieldDicts
2388  );
2389  receiveFields<volSymmTensorField>
2390  (
2391  sendProc,
2392  allFieldNames,
2393  domainMesh,
2394  vsytf,
2395  fieldDicts
2396  );
2397  receiveFields<volTensorField>
2398  (
2399  sendProc,
2400  allFieldNames,
2401  domainMesh,
2402  vtf,
2403  fieldDicts
2404  );
2405 
2406  // Surface fields
2407  receiveFields<surfaceScalarField>
2408  (
2409  sendProc,
2410  allFieldNames,
2411  domainMesh,
2412  ssf,
2413  fieldDicts
2414  );
2415  receiveFields<surfaceVectorField>
2416  (
2417  sendProc,
2418  allFieldNames,
2419  domainMesh,
2420  svf,
2421  fieldDicts
2422  );
2423  receiveFields<surfaceSphericalTensorField>
2424  (
2425  sendProc,
2426  allFieldNames,
2427  domainMesh,
2428  ssptf,
2429  fieldDicts
2430  );
2431  receiveFields<surfaceSymmTensorField>
2432  (
2433  sendProc,
2434  allFieldNames,
2435  domainMesh,
2436  ssytf,
2437  fieldDicts
2438  );
2439  receiveFields<surfaceTensorField>
2440  (
2441  sendProc,
2442  allFieldNames,
2443  domainMesh,
2444  stf,
2445  fieldDicts
2446  );
2447 
2448  // Dimensioned fields
2449  receiveFields<volScalarField::Internal>
2450  (
2451  sendProc,
2452  allFieldNames,
2453  domainMesh,
2454  dsf,
2455  fieldDicts
2456  );
2457  receiveFields<volVectorField::Internal>
2458  (
2459  sendProc,
2460  allFieldNames,
2461  domainMesh,
2462  dvf,
2463  fieldDicts
2464  );
2465  receiveFields<volSphericalTensorField::Internal>
2466  (
2467  sendProc,
2468  allFieldNames,
2469  domainMesh,
2470  dstf,
2471  fieldDicts
2472  );
2473  receiveFields<volSymmTensorField::Internal>
2474  (
2475  sendProc,
2476  allFieldNames,
2477  domainMesh,
2478  dsytf,
2479  fieldDicts
2480  );
2481  receiveFields<volTensorField::Internal>
2482  (
2483  sendProc,
2484  allFieldNames,
2485  domainMesh,
2486  dtf,
2487  fieldDicts
2488  );
2489  }
2490  const fvMesh& domainMesh = domainMeshPtr();
2491 
2492 
2493  constructCellMap[sendProc] = identity(domainMesh.nCells());
2494  constructFaceMap[sendProc] = identity(domainMesh.nFaces(), 1);
2495  constructPointMap[sendProc] = identity(domainMesh.nPoints());
2496  constructPatchMap[sendProc] =
2497  identity(domainMesh.boundaryMesh().size());
2498 
2499 
2500  // Print a bit.
2501  if (debug)
2502  {
2503  Pout<< nl << "RECEIVED MESH FROM:" << sendProc << endl;
2504  printMeshInfo(domainMesh);
2505  printFieldInfo<volScalarField>(domainMesh);
2506  printFieldInfo<volVectorField>(domainMesh);
2507  printFieldInfo<volSphericalTensorField>(domainMesh);
2508  printFieldInfo<volSymmTensorField>(domainMesh);
2509  printFieldInfo<volTensorField>(domainMesh);
2510  printFieldInfo<surfaceScalarField>(domainMesh);
2511  printFieldInfo<surfaceVectorField>(domainMesh);
2512  printFieldInfo<surfaceSphericalTensorField>(domainMesh);
2513  printFieldInfo<surfaceSymmTensorField>(domainMesh);
2514  printFieldInfo<surfaceTensorField>(domainMesh);
2515  }
2516 
2517 
2518  // Now this mesh we received (from sendProc) needs to be merged
2519  // with the current mesh. On the current mesh we have for all
2520  // boundaryfaces the original face and processor. See if we can
2521  // match these up to the received domainSourceFace and
2522  // domainSourceProc.
2523  labelList masterCoupledFaces;
2524  labelList slaveCoupledFaces;
2525  findCouples
2526  (
2527  mesh_,
2528 
2529  sourceFace,
2530  sourceProc,
2531  sourcePatch,
2532 
2533  sendProc,
2534  domainMesh,
2535  domainSourceFace,
2536  domainSourceProc,
2537  domainSourcePatch,
2538 
2539  masterCoupledFaces,
2540  slaveCoupledFaces
2541  );
2542 
2543  // Generate additional coupling info (points, edges) from
2544  // faces-that-match
2545  faceCoupleInfo couples
2546  (
2547  mesh_,
2548  masterCoupledFaces,
2549  domainMesh,
2550  slaveCoupledFaces,
2551  mergeTol_, // merge tolerance
2552  true, // faces align
2553  true, // couples are ordered already
2554  false
2555  );
2556 
2557 
2558  // Add domainMesh to mesh
2559  // ~~~~~~~~~~~~~~~~~~~~~~
2560 
2562  (
2563  mesh_,
2564  domainMesh,
2565  couples,
2566  false, // no parallel comms
2567  true // fake complete mapping
2568  );
2569 
2570  // Update mesh data: sourceFace,sourceProc for added
2571  // mesh.
2572 
2573  sourceFace = mapBoundaryData
2574  (
2575  mesh_,
2576  map(),
2577  sourceFace,
2578  domainMesh.nInternalFaces(),
2579  domainSourceFace
2580  );
2581  sourceProc = mapBoundaryData
2582  (
2583  mesh_,
2584  map(),
2585  sourceProc,
2586  domainMesh.nInternalFaces(),
2587  domainSourceProc
2588  );
2589  sourcePatch = mapBoundaryData
2590  (
2591  mesh_,
2592  map(),
2593  sourcePatch,
2594  domainMesh.nInternalFaces(),
2595  domainSourcePatch
2596  );
2597  sourceNewNbrProc = mapBoundaryData
2598  (
2599  mesh_,
2600  map(),
2601  sourceNewNbrProc,
2602  domainMesh.nInternalFaces(),
2603  domainSourceNewNbrProc
2604  );
2605  // Update pointMaster data
2606  sourcePointMaster = mapPointData
2607  (
2608  mesh_,
2609  map(),
2610  sourcePointMaster,
2611  domainSourcePointMaster
2612  );
2613 
2614 
2615  // Update all addressing so xxProcAddressing points to correct
2616  // item in masterMesh.
2617  const labelList& oldCellMap = map().oldCellMap();
2618  const labelList& oldFaceMap = map().oldFaceMap();
2619  const labelList& oldPointMap = map().oldPointMap();
2620  const labelList& oldPatchMap = map().oldPatchMap();
2621 
2622  //Note: old mesh faces never flipped!
2623  forAll(constructPatchMap, proci)
2624  {
2625  if (proci != sendProc && constructPatchMap[proci].size())
2626  {
2627  // Processor already in mesh (either myProcNo or received)
2628  inplaceRenumber(oldCellMap, constructCellMap[proci]);
2629  inplaceRenumberWithFlip
2630  (
2631  oldFaceMap,
2632  false,
2633  true,
2634  constructFaceMap[proci]
2635  );
2636  inplaceRenumber(oldPointMap, constructPointMap[proci]);
2637  inplaceRenumber(oldPatchMap, constructPatchMap[proci]);
2638  }
2639  }
2640 
2641 
2642  labelHashSet flippedAddedFaces;
2643  {
2644  // Find out if any faces of domain mesh were flipped (boundary
2645  // faces becoming internal)
2646  const label nBnd = domainMesh.nBoundaryFaces();
2647  flippedAddedFaces.resize(nBnd/4);
2648 
2649  for
2650  (
2651  label domainFaceI = domainMesh.nInternalFaces();
2652  domainFaceI < domainMesh.nFaces();
2653  domainFaceI++
2654  )
2655  {
2656  label newFaceI = map().addedFaceMap()[domainFaceI];
2657  label newCellI = mesh_.faceOwner()[newFaceI];
2658 
2659  label domainCellI = domainMesh.faceOwner()[domainFaceI];
2660 
2661  if (newCellI != map().addedCellMap()[domainCellI])
2662  {
2663  flippedAddedFaces.insert(domainFaceI);
2664  }
2665  }
2666  }
2667 
2668 
2669  // Added processor
2670  inplaceRenumber(map().addedCellMap(), constructCellMap[sendProc]);
2671  // Add flip
2672  for (const label domainFaceI : flippedAddedFaces)
2673  {
2674  label& val = constructFaceMap[sendProc][domainFaceI];
2675  val = -val;
2676  }
2677  inplaceRenumberWithFlip
2678  (
2679  map().addedFaceMap(),
2680  false,
2681  true, // constructFaceMap has flip sign
2682  constructFaceMap[sendProc]
2683  );
2684  inplaceRenumber(map().addedPointMap(), constructPointMap[sendProc]);
2685  inplaceRenumber(map().addedPatchMap(), constructPatchMap[sendProc]);
2686 
2687  if (debug)
2688  {
2689  Pout<< nl << "MERGED MESH FROM:" << sendProc << endl;
2690  printMeshInfo(mesh_);
2691  printFieldInfo<volScalarField>(mesh_);
2692  printFieldInfo<volVectorField>(mesh_);
2693  printFieldInfo<volSphericalTensorField>(mesh_);
2694  printFieldInfo<volSymmTensorField>(mesh_);
2695  printFieldInfo<volTensorField>(mesh_);
2696  printFieldInfo<surfaceScalarField>(mesh_);
2697  printFieldInfo<surfaceVectorField>(mesh_);
2698  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2699  printFieldInfo<surfaceSymmTensorField>(mesh_);
2700  printFieldInfo<surfaceTensorField>(mesh_);
2701  Pout<< nl << endl;
2702  }
2703  }
2704  }
2705 
2706  UPstream::parRun(oldParRun); // Restore parallel state
2707 
2708 
2709  // Print a bit.
2710  if (debug)
2711  {
2712  Pout<< nl << "REDISTRIBUTED MESH:" << endl;
2713  printMeshInfo(mesh_);
2714  printFieldInfo<volScalarField>(mesh_);
2715  printFieldInfo<volVectorField>(mesh_);
2716  printFieldInfo<volSphericalTensorField>(mesh_);
2717  printFieldInfo<volSymmTensorField>(mesh_);
2718  printFieldInfo<volTensorField>(mesh_);
2719  printFieldInfo<surfaceScalarField>(mesh_);
2720  printFieldInfo<surfaceVectorField>(mesh_);
2721  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2722  printFieldInfo<surfaceSymmTensorField>(mesh_);
2723  printFieldInfo<surfaceTensorField>(mesh_);
2724  Pout<< nl << endl;
2725  }
2726 
2727 
2728  // See if any originally shared points need to be merged. Note: does
2729  // parallel comms. After this points and edges should again be consistent.
2730  mergeSharedPoints(sourcePointMaster, constructPointMap);
2731 
2732 
2733  // Add processorPatches
2734  // ~~~~~~~~~~~~~~~~~~~~
2735 
2736  // Per neighbour processor, per originating patch, the patchID
2737  // For faces resulting from internal faces or normal processor patches
2738  // the originating patch is -1. For cyclics this is the cyclic patchID.
2739  List<Map<label>> procPatchID;
2740 
2741  // Add processor and processorCyclic patches.
2742  addProcPatches(sourceNewNbrProc, sourcePatch, procPatchID);
2743 
2744  // Put faces into correct patch. Note that we now have proper
2745  // processorPolyPatches again so repatching will take care of coupled face
2746  // ordering.
2747 
2748  // Get boundary faces to be repatched. Is -1 or new patchID
2749  labelList newPatchID
2750  (
2751  getBoundaryPatch
2752  (
2753  sourceNewNbrProc,
2754  sourcePatch,
2755  procPatchID
2756  )
2757  );
2758 
2759  // Change patches. Since this might change ordering of coupled faces
2760  // we also need to adapt our constructMaps.
2761  repatch(newPatchID, constructFaceMap);
2762 
2763  // Bit of hack: processorFvPatchField does not get reset since created
2764  // from nothing so explicitly reset.
2765  initPatchFields<volScalarField, processorFvPatchField<scalar>>
2766  (
2767  Zero
2768  );
2769  initPatchFields<volVectorField, processorFvPatchField<vector>>
2770  (
2771  Zero
2772  );
2773  initPatchFields
2774  <
2777  >
2778  (
2779  Zero
2780  );
2781  initPatchFields<volSymmTensorField, processorFvPatchField<symmTensor>>
2782  (
2783  Zero
2784  );
2785  initPatchFields<volTensorField, processorFvPatchField<tensor>>
2786  (
2787  Zero
2788  );
2789 
2790 
2791  mesh_.setInstance(mesh_.time().timeName());
2792 
2793 
2794  // Print a bit
2795  if (debug)
2796  {
2797  Pout<< nl << "FINAL MESH:" << endl;
2798  printMeshInfo(mesh_);
2799  printFieldInfo<volScalarField>(mesh_);
2800  printFieldInfo<volVectorField>(mesh_);
2801  printFieldInfo<volSphericalTensorField>(mesh_);
2802  printFieldInfo<volSymmTensorField>(mesh_);
2803  printFieldInfo<volTensorField>(mesh_);
2804  printFieldInfo<surfaceScalarField>(mesh_);
2805  printFieldInfo<surfaceVectorField>(mesh_);
2806  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2807  printFieldInfo<surfaceSymmTensorField>(mesh_);
2808  printFieldInfo<surfaceTensorField>(mesh_);
2809  Pout<< nl << endl;
2810  }
2811 
2812  // Collect all maps and return
2814  (
2815  mesh_,
2816 
2817  nOldPoints,
2818  nOldFaces,
2819  nOldCells,
2820  std::move(oldPatchStarts),
2821  std::move(oldPatchNMeshPoints),
2822 
2823  std::move(subPointMap),
2824  std::move(subFaceMap),
2825  std::move(subCellMap),
2826  std::move(subPatchMap),
2827 
2828  std::move(constructPointMap),
2829  std::move(constructFaceMap),
2830  std::move(constructCellMap),
2831  std::move(constructPatchMap),
2832 
2833  true, // subFaceMap has flip
2834  true // constructFaceMap has flip
2835  );
2836 }
2837 
2838 
2839 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
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:71
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:1696
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:104
Foam::distribution
Accumulating histogram of values. Specified bin resolution automatic generation of bins.
Definition: distribution.H:61
Foam::UPstream::commsTypes::nonBlocking
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::VectorSpace< Vector< Cmpt >, Cmpt, 3 >::one
static const Vector< Cmpt > 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
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobjectI.H:70
polyRemovePoint.H
cyclicACMIPolyPatch.H
Foam::UOPstream
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:57
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
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:62
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::primitiveMesh::nInternalFaces
label nInternalFaces() const
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Definition: gatherScatterList.C:215
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
Foam::primitiveMesh::nFaces
label nFaces() const
Number of mesh faces.
Definition: primitiveMeshI.H:90
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:87
Foam::polyPatch::coupled
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:329
polyTopoChange.H
Foam::UPstream::parRun
static bool & parRun()
Test if this a parallel run, or allow modify access.
Definition: UPstream.H:434
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::polyMesh::cellZones
const cellZoneMesh & cellZones() const
Return cell zone mesh.
Definition: polyMesh.H:492
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::syncTools::swapBoundaryFaceList
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:439
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:350
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::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:638
Foam::fvMeshSubset::faceFlipMap
const labelList & faceFlipMap() const
Return face map with sign to encode flipped faces.
Definition: fvMeshSubsetI.H:80
nProcPatches
const label nProcPatches
Definition: convertProcessorPatches.H:171
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:593
fvMeshAdder.H
Foam::fvMeshDistribute::generateTestField
static tmp< surfaceScalarField > generateTestField(const fvMesh &)
Generate a test field on faces.
Definition: fvMeshDistribute.C:396
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:72
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:486
Foam::fvBoundaryMesh
Foam::fvBoundaryMesh.
Definition: fvBoundaryMesh.H:56
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:59
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:955
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:228
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
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:307
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:65
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::polyMesh::pointZones
const pointZoneMesh & pointZones() const
Return point zone mesh.
Definition: polyMesh.H:480
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:459
Foam::HashTable::resize
void resize(const label sz)
Resize the hash table for efficiency.
Definition: HashTable.C:553
processorCyclicFvPatchField.H
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:43
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:62
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
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, labelPair::Hash<> > 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. This will start receives.
Definition: PstreamBuffers.C:80
faceCoupleInfo.H
newPointi
label newPointi
Definition: readKivaGrid.H:496
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::cyclicACMIPolyPatch::nonOverlapPatchID
virtual label nonOverlapPatchID() const
Non-overlapping patch ID.
Definition: cyclicACMIPolyPatch.C:761
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:121
Foam::primitiveMesh::nBoundaryFaces
label nBoundaryFaces() const
Number of boundary faces (== nFaces - nInternalFaces)
Definition: primitiveMeshI.H:84
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 a pointer to a new patch created on freestore from.
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:83
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::zone::name
const word & name() const
Return name.
Definition: zone.H:158
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:313
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:483
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::fvMesh::boundary
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:679
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:215
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:381
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
fvMeshDistribute.H
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:464
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::fvsPatchField::patch
const fvPatch & patch() const
Return patch.
Definition: fvsPatchField.H:281
fvMeshTools.H
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::Vector< scalar >
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:275
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::primitiveMesh::nPoints
label nPoints() const
Number of mesh points.
Definition: primitiveMeshI.H:37
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::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:181
Foam::fvMeshDistribute::testField
static void testField(const surfaceScalarField &)
Check whether field consistent with face orientation.
Definition: fvMeshDistribute.C:446
Foam::fvMeshDistribute::distribute
autoPtr< mapDistributePolyMesh > distribute(const labelList &dist)
Send cells to neighbours according to distribution.
Definition: fvMeshDistribute.C:1720
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::faceCoupleInfo
Container for information needed to couple to meshes. When constructed from two meshes and a geometri...
Definition: faceCoupleInfo.H:160
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::wordHashSet
HashSet< word > wordHashSet
A HashSet with word keys.
Definition: HashSet.H:406
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:275
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:124
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::cyclicACMIPolyPatch
Cyclic patch for Arbitrarily Coupled Mesh Interface (ACMI).
Definition: cyclicACMIPolyPatch.H:79
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:80
Foam::GeometricField< scalar, fvsPatchField, surfaceMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:123
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::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::patchIdentifier::name
const word & name() const
The patch name.
Definition: patchIdentifier.H:134
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:303
Foam::polyMeshAdder::mergePoints
static void mergePoints(const polyMesh &, const Map< label > &pointToMaster, polyTopoChange &meshMod)
Helper: Merge points.
Definition: polyMeshAdder.C:2212
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:446
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