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