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-2018 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 "syncTools.H"
41 #include "CompactListList.H"
42 #include "fvMeshTools.H"
43 #include "ListOps.H"
44 #include "globalIndex.H"
45 
46 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
47 
48 namespace Foam
49 {
50  defineTypeNameAndDebug(fvMeshDistribute, 0);
51 
52 //- Less function class that can be used for sorting processor patches
54 {
55  const labelList& nbrProc_;
56  const labelList& referPatchID_;
57 
58 public:
59 
60  lessProcPatches( const labelList& nbrProc, const labelList& referPatchID)
61  :
62  nbrProc_(nbrProc),
63  referPatchID_(referPatchID)
64  {}
65 
66  bool operator()(const label a, const label b)
67  {
68  if (nbrProc_[a] < nbrProc_[b])
69  {
70  return true;
71  }
72  else if (nbrProc_[a] > nbrProc_[b])
73  {
74  return false;
75  }
76  else
77  {
78  // Equal neighbour processor
79  return referPatchID_[a] < referPatchID_[b];
80  }
81  }
82 };
83 
84 }
85 
86 
87 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
88 
89 void Foam::fvMeshDistribute::inplaceRenumberWithFlip
90 (
91  const labelUList& oldToNew,
92  const bool oldToNewHasFlip,
93  const bool lstHasFlip,
94  labelUList& lst
95 )
96 {
97  if (!lstHasFlip && !oldToNewHasFlip)
98  {
99  Foam::inplaceRenumber(oldToNew, lst);
100  }
101  else
102  {
103  // Either input data or map encodes sign so result encodes sign
104 
105  forAll(lst, elemI)
106  {
107  // Extract old value and sign
108  label val = lst[elemI];
109  label sign = 1;
110  if (lstHasFlip)
111  {
112  if (val > 0)
113  {
114  val = val-1;
115  }
116  else if (val < 0)
117  {
118  val = -val-1;
119  sign = -1;
120  }
121  else
122  {
124  << "Problem : zero value " << val
125  << " at index " << elemI << " out of " << lst.size()
126  << " list with flip bit" << exit(FatalError);
127  }
128  }
129 
130 
131  // Lookup new value and possibly change sign
132  label newVal = oldToNew[val];
133 
134  if (oldToNewHasFlip)
135  {
136  if (newVal > 0)
137  {
138  newVal = newVal-1;
139  }
140  else if (newVal < 0)
141  {
142  newVal = -newVal-1;
143  sign = -sign;
144  }
145  else
146  {
148  << "Problem : zero value " << newVal
149  << " at index " << elemI << " out of "
150  << oldToNew.size()
151  << " list with flip bit" << exit(FatalError);
152  }
153  }
154 
155 
156  // Encode new value and sign
157  lst[elemI] = sign*(newVal+1);
158  }
159  }
160 }
161 
162 
163 Foam::labelList Foam::fvMeshDistribute::select
164 (
165  const bool selectEqual,
166  const labelList& values,
167  const label value
168 )
169 {
170  label n = 0;
171 
172  forAll(values, i)
173  {
174  if (selectEqual == (values[i] == value))
175  {
176  n++;
177  }
178  }
179 
180  labelList indices(n);
181  n = 0;
182 
183  forAll(values, i)
184  {
185  if (selectEqual == (values[i] == value))
186  {
187  indices[n++] = i;
188  }
189  }
190  return indices;
191 }
192 
193 
194 // Check all procs have same names and in exactly same order.
195 void Foam::fvMeshDistribute::checkEqualWordList
196 (
197  const string& msg,
198  const wordList& lst
199 )
200 {
201  List<wordList> allNames(Pstream::nProcs());
202  allNames[Pstream::myProcNo()] = lst;
203  Pstream::gatherList(allNames);
204  Pstream::scatterList(allNames);
205 
206  for (label proci = 1; proci < Pstream::nProcs(); proci++)
207  {
208  if (allNames[proci] != allNames[0])
209  {
211  << "When checking for equal " << msg.c_str() << " :" << endl
212  << "processor0 has:" << allNames[0] << endl
213  << "processor" << proci << " has:" << allNames[proci] << endl
214  << msg.c_str() << " need to be synchronised on all processors."
215  << exit(FatalError);
216  }
217  }
218 }
219 
220 
221 Foam::wordList Foam::fvMeshDistribute::mergeWordList(const wordList& procNames)
222 {
223  List<wordList> allNames(Pstream::nProcs());
224  allNames[Pstream::myProcNo()] = procNames;
225  Pstream::gatherList(allNames);
226  Pstream::scatterList(allNames);
227 
228  HashSet<word> mergedNames;
229  forAll(allNames, proci)
230  {
231  forAll(allNames[proci], i)
232  {
233  mergedNames.insert(allNames[proci][i]);
234  }
235  }
236  return mergedNames.toc();
237 }
238 
239 
240 // Print some info on mesh.
242 {
243  Pout<< "Primitives:" << nl
244  << " points :" << mesh.nPoints() << nl
245  << " bb :" << boundBox(mesh.points(), false) << nl
246  << " internalFaces:" << mesh.nInternalFaces() << nl
247  << " faces :" << mesh.nFaces() << nl
248  << " cells :" << mesh.nCells() << nl;
249 
250  const fvBoundaryMesh& patches = mesh.boundary();
251 
252  Pout<< "Patches:" << endl;
253  forAll(patches, patchi)
254  {
255  const polyPatch& pp = patches[patchi].patch();
256 
257  Pout<< " " << patchi << " name:" << pp.name()
258  << " size:" << pp.size()
259  << " start:" << pp.start()
260  << " type:" << pp.type()
261  << endl;
262  }
263 
264  if (mesh.pointZones().size())
265  {
266  Pout<< "PointZones:" << endl;
267  forAll(mesh.pointZones(), zoneI)
268  {
269  const pointZone& pz = mesh.pointZones()[zoneI];
270  Pout<< " " << zoneI << " name:" << pz.name()
271  << " size:" << pz.size()
272  << endl;
273  }
274  }
275  if (mesh.faceZones().size())
276  {
277  Pout<< "FaceZones:" << endl;
278  forAll(mesh.faceZones(), zoneI)
279  {
280  const faceZone& fz = mesh.faceZones()[zoneI];
281  Pout<< " " << zoneI << " name:" << fz.name()
282  << " size:" << fz.size()
283  << endl;
284  }
285  }
286  if (mesh.cellZones().size())
287  {
288  Pout<< "CellZones:" << endl;
289  forAll(mesh.cellZones(), zoneI)
290  {
291  const cellZone& cz = mesh.cellZones()[zoneI];
292  Pout<< " " << zoneI << " name:" << cz.name()
293  << " size:" << cz.size()
294  << endl;
295  }
296  }
297 }
298 
299 
301 (
302  const primitiveMesh& mesh,
303  const labelList& sourceFace,
304  const labelList& sourceProc,
305  const labelList& sourcePatch,
306  const labelList& sourceNewNbrProc
307 )
308 {
309  Pout<< nl
310  << "Current coupling info:"
311  << endl;
312 
313  forAll(sourceFace, bFacei)
314  {
315  label meshFacei = mesh.nInternalFaces() + bFacei;
316 
317  Pout<< " meshFace:" << meshFacei
318  << " fc:" << mesh.faceCentres()[meshFacei]
319  << " connects to proc:" << sourceProc[bFacei]
320  << "/face:" << sourceFace[bFacei]
321  << " which will move to proc:" << sourceNewNbrProc[bFacei]
322  << endl;
323  }
324 }
325 
326 
327 // Finds (non-empty) patch that exposed internal and proc faces can be put into.
328 Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
329 {
330  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
331 
332  label nonEmptyPatchi = -1;
333 
334  forAllReverse(patches, patchi)
335  {
336  const polyPatch& pp = patches[patchi];
337 
338  if (!isA<emptyPolyPatch>(pp) && !pp.coupled())
339  {
340  nonEmptyPatchi = patchi;
341  break;
342  }
343  }
344 
345  if (nonEmptyPatchi == -1)
346  {
348  << "Cannot find a patch which is neither of type empty nor"
349  << " coupled in patches " << patches.names() << endl
350  << "There has to be at least one such patch for"
351  << " distribution to work" << abort(FatalError);
352  }
353 
354  if (debug)
355  {
356  Pout<< "findNonEmptyPatch : using patch " << nonEmptyPatchi
357  << " name:" << patches[nonEmptyPatchi].name()
358  << " type:" << patches[nonEmptyPatchi].type()
359  << " to put exposed faces into." << endl;
360  }
361 
362 
363  // Do additional test for processor patches intermingled with non-proc
364  // patches.
365  label procPatchi = -1;
366 
367  forAll(patches, patchi)
368  {
369  if (isA<processorPolyPatch>(patches[patchi]))
370  {
371  procPatchi = patchi;
372  }
373  else if (procPatchi != -1)
374  {
376  << "Processor patches should be at end of patch list."
377  << endl
378  << "Have processor patch " << procPatchi
379  << " followed by non-processor patch " << patchi
380  << " in patches " << patches.names()
381  << abort(FatalError);
382  }
383  }
384 
385  return nonEmptyPatchi;
386 }
387 
388 
389 // Delete all processor patches. Move any processor faces into the last
390 // non-processor patch.
391 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::deleteProcPatches
392 (
393  const label destinationPatch
394 )
395 {
396  // New patchID per boundary faces to be repatched. Is -1 (no change)
397  // or new patchID
398  labelList newPatchID(mesh_.nFaces() - mesh_.nInternalFaces(), -1);
399 
400  label nProcPatches = 0;
401 
402  forAll(mesh_.boundaryMesh(), patchi)
403  {
404  const polyPatch& pp = mesh_.boundaryMesh()[patchi];
405 
406  if (isA<processorPolyPatch>(pp))
407  {
408  if (debug)
409  {
410  Pout<< "Moving all faces of patch " << pp.name()
411  << " into patch " << destinationPatch
412  << endl;
413  }
414 
415  label offset = pp.start() - mesh_.nInternalFaces();
416 
417  forAll(pp, i)
418  {
419  newPatchID[offset+i] = destinationPatch;
420  }
421 
422  nProcPatches++;
423  }
424  }
425 
426  // Note: order of boundary faces been kept the same since the
427  // destinationPatch is at the end and we have visited the patches in
428  // incremental order.
429  labelListList dummyFaceMaps;
430  autoPtr<mapPolyMesh> map = repatch(newPatchID, dummyFaceMaps);
431 
432 
433  // Delete (now empty) processor patches.
434  {
435  labelList oldToNew(identity(mesh_.boundaryMesh().size()));
436  label newI = 0;
437  // Non processor patches first
438  forAll(mesh_.boundaryMesh(), patchi)
439  {
440  if (!isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
441  {
442  oldToNew[patchi] = newI++;
443  }
444  }
445  label nNonProcPatches = newI;
446 
447  // Processor patches as last
448  forAll(mesh_.boundaryMesh(), patchi)
449  {
450  if (isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
451  {
452  oldToNew[patchi] = newI++;
453  }
454  }
455  fvMeshTools::reorderPatches(mesh_, oldToNew, nNonProcPatches, false);
456  }
457 
458  return map;
459 }
460 
461 
462 // Repatch the mesh.
463 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
464 (
465  const labelList& newPatchID, // per boundary face -1 or new patchID
466  labelListList& constructFaceMap
467 )
468 {
469  polyTopoChange meshMod(mesh_);
470 
471  forAll(newPatchID, bFacei)
472  {
473  if (newPatchID[bFacei] != -1)
474  {
475  label facei = mesh_.nInternalFaces() + bFacei;
476 
477  label zoneID = mesh_.faceZones().whichZone(facei);
478  bool zoneFlip = false;
479 
480  if (zoneID >= 0)
481  {
482  const faceZone& fZone = mesh_.faceZones()[zoneID];
483  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
484  }
485 
486  meshMod.setAction
487  (
489  (
490  mesh_.faces()[facei], // modified face
491  facei, // label of face
492  mesh_.faceOwner()[facei], // owner
493  -1, // neighbour
494  false, // face flip
495  newPatchID[bFacei], // patch for face
496  false, // remove from zone
497  zoneID, // zone for face
498  zoneFlip // face flip in zone
499  )
500  );
501  }
502  }
503 
504 
505  // Do mapping of fields from one patchField to the other ourselves since
506  // is currently not supported by updateMesh.
507 
508  // Store boundary fields (we only do this for surfaceFields)
510  saveBoundaryFields<scalar, surfaceMesh>(sFlds);
512  saveBoundaryFields<vector, surfaceMesh>(vFlds);
514  saveBoundaryFields<sphericalTensor, surfaceMesh>(sptFlds);
516  saveBoundaryFields<symmTensor, surfaceMesh>(sytFlds);
518  saveBoundaryFields<tensor, surfaceMesh>(tFlds);
519 
520  // Change the mesh (no inflation). Note: parallel comms allowed.
521  //
522  // NOTE: there is one very particular problem with this ordering.
523  // We first create the processor patches and use these to merge out
524  // shared points (see mergeSharedPoints below). So temporarily points
525  // and edges do not match!
526 
527  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
528 
529  // Update fields. No inflation, parallel sync.
530  mesh_.updateMesh(map);
531 
532  // Map patch fields using stored boundary fields. Note: assumes order
533  // of fields has not changed in object registry!
534  mapBoundaryFields<scalar, surfaceMesh>(map, sFlds);
535  mapBoundaryFields<vector, surfaceMesh>(map, vFlds);
536  mapBoundaryFields<sphericalTensor, surfaceMesh>(map, sptFlds);
537  mapBoundaryFields<symmTensor, surfaceMesh>(map, sytFlds);
538  mapBoundaryFields<tensor, surfaceMesh>(map, tFlds);
539 
540 
541  // Move mesh (since morphing does not do this)
542  if (map().hasMotionPoints())
543  {
544  mesh_.movePoints(map().preMotionPoints());
545  }
546 
547  // Adapt constructMaps.
548 
549  if (debug)
550  {
551  label index = findIndex(map().reverseFaceMap(), -1);
552 
553  if (index != -1)
554  {
556  << "reverseFaceMap contains -1 at index:"
557  << index << endl
558  << "This means that the repatch operation was not just"
559  << " a shuffle?" << abort(FatalError);
560  }
561  }
562 
563  forAll(constructFaceMap, proci)
564  {
565  inplaceRenumberWithFlip
566  (
567  map().reverseFaceMap(),
568  false,
569  true,
570  constructFaceMap[proci]
571  );
572  }
573 
574 
575  return map;
576 }
577 
578 
579 // Detect shared points. Need processor patches to be present.
580 // Background: when adding bits of mesh one can get points which
581 // share the same position but are only detectable to be topologically
582 // the same point when doing parallel analysis. This routine will
583 // merge those points.
584 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
585 (
586  const labelList& pointToGlobalMaster,
587  labelListList& constructPointMap
588 )
589 {
590  // Find out which sets of points get merged and create a map from
591  // mesh point to unique point.
592 
593  label nShared = 0;
594  forAll(pointToGlobalMaster, pointi)
595  {
596  if (pointToGlobalMaster[pointi] != -1)
597  {
598  nShared++;
599  }
600  }
601 
602  Map<label> globalMasterToLocalMaster(2*nShared);
603  Map<label> pointToMaster(2*nShared);
604 
605  forAll(pointToGlobalMaster, pointi)
606  {
607  label globali = pointToGlobalMaster[pointi];
608  if (globali != -1)
609  {
610  Map<label>::const_iterator iter = globalMasterToLocalMaster.find
611  (
612  globali
613  );
614 
615  if (iter == globalMasterToLocalMaster.end())
616  {
617  // Found first point. Designate as master
618  globalMasterToLocalMaster.insert(globali, pointi);
619  pointToMaster.insert(pointi, pointi);
620  }
621  else
622  {
623  pointToMaster.insert(pointi, iter());
624  }
625  }
626  }
627 
628  if (returnReduce(pointToMaster.size(), sumOp<label>()) == 0)
629  {
630  return autoPtr<mapPolyMesh>(nullptr);
631  }
632 
633 
634  polyTopoChange meshMod(mesh_);
635 
636  fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
637 
638  // Change the mesh (no inflation). Note: parallel comms allowed.
639  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
640 
641  // Update fields. No inflation, parallel sync.
642  mesh_.updateMesh(map);
643 
644  // Adapt constructMaps for merged points.
645  forAll(constructPointMap, proci)
646  {
647  labelList& constructMap = constructPointMap[proci];
648 
649  forAll(constructMap, i)
650  {
651  label oldPointi = constructMap[i];
652 
653  label newPointi = map().reversePointMap()[oldPointi];
654 
655  if (newPointi < -1)
656  {
657  constructMap[i] = -newPointi-2;
658  }
659  else if (newPointi >= 0)
660  {
661  constructMap[i] = newPointi;
662  }
663  else
664  {
666  << "Problem. oldPointi:" << oldPointi
667  << " newPointi:" << newPointi << abort(FatalError);
668  }
669  }
670  }
671  return map;
672 }
673 
674 
675 void Foam::fvMeshDistribute::getCouplingData
676 (
677  const labelList& distribution,
678  labelList& sourceFace,
679  labelList& sourceProc,
680  labelList& sourcePatch,
681  labelList& sourceNewNbrProc,
682  labelList& sourcePointMaster
683 ) const
684 {
685  // Construct the coupling information for all (boundary) faces and
686  // points
687 
688  label nBnd = mesh_.nFaces() - mesh_.nInternalFaces();
689  sourceFace.setSize(nBnd);
690  sourceProc.setSize(nBnd);
691  sourcePatch.setSize(nBnd);
692  sourceNewNbrProc.setSize(nBnd);
693 
694  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
695 
696  // Get neighbouring meshFace labels and new processor of coupled boundaries.
697  labelList nbrFaces(nBnd, -1);
698  labelList nbrNewNbrProc(nBnd, -1);
699 
700  forAll(patches, patchi)
701  {
702  const polyPatch& pp = patches[patchi];
703 
704  if (pp.coupled())
705  {
706  label offset = pp.start() - mesh_.nInternalFaces();
707 
708  // Mesh labels of faces on this side
709  forAll(pp, i)
710  {
711  label bndI = offset + i;
712  nbrFaces[bndI] = pp.start()+i;
713  }
714 
715  // Which processor they will end up on
716  SubList<label>(nbrNewNbrProc, pp.size(), offset) =
717  UIndirectList<label>(distribution, pp.faceCells())();
718  }
719  }
720 
721 
722  // Exchange the boundary data
723  syncTools::swapBoundaryFaceList(mesh_, nbrFaces);
724  syncTools::swapBoundaryFaceList(mesh_, nbrNewNbrProc);
725 
726 
727  forAll(patches, patchi)
728  {
729  const polyPatch& pp = patches[patchi];
730  label offset = pp.start() - mesh_.nInternalFaces();
731 
732  if (isA<processorPolyPatch>(pp))
733  {
734  const processorPolyPatch& procPatch =
735  refCast<const processorPolyPatch>(pp);
736 
737  // Check which of the two faces we store.
738 
739  if (procPatch.owner())
740  {
741  // Use my local face labels
742  forAll(pp, i)
743  {
744  label bndI = offset + i;
745  sourceFace[bndI] = pp.start()+i;
746  sourceProc[bndI] = Pstream::myProcNo();
747  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
748  }
749  }
750  else
751  {
752  // Use my neighbours face labels
753  forAll(pp, i)
754  {
755  label bndI = offset + i;
756  sourceFace[bndI] = nbrFaces[bndI];
757  sourceProc[bndI] = procPatch.neighbProcNo();
758  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
759  }
760  }
761 
762 
763  label patchi = -1;
764  if (isA<processorCyclicPolyPatch>(pp))
765  {
766  patchi = refCast<const processorCyclicPolyPatch>
767  (
768  pp
769  ).referPatchID();
770  }
771 
772  forAll(pp, i)
773  {
774  label bndI = offset + i;
775  sourcePatch[bndI] = patchi;
776  }
777  }
778  else if (isA<cyclicPolyPatch>(pp))
779  {
780  const cyclicPolyPatch& cpp = refCast<const cyclicPolyPatch>(pp);
781 
782  if (cpp.owner())
783  {
784  forAll(pp, i)
785  {
786  label bndI = offset + i;
787  sourceFace[bndI] = pp.start()+i;
788  sourceProc[bndI] = Pstream::myProcNo();
789  sourcePatch[bndI] = patchi;
790  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
791  }
792  }
793  else
794  {
795  forAll(pp, i)
796  {
797  label bndI = offset + i;
798  sourceFace[bndI] = nbrFaces[bndI];
799  sourceProc[bndI] = Pstream::myProcNo();
800  sourcePatch[bndI] = patchi;
801  sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
802  }
803  }
804  }
805  else
806  {
807  // Normal (physical) boundary
808  forAll(pp, i)
809  {
810  label bndI = offset + i;
811  sourceFace[bndI] = -1;
812  sourceProc[bndI] = -1;
813  sourcePatch[bndI] = patchi;
814  sourceNewNbrProc[bndI] = -1;
815  }
816  }
817  }
818 
819 
820  // Collect coupled (collocated) points
821  sourcePointMaster.setSize(mesh_.nPoints());
822  sourcePointMaster = -1;
823  {
824  // Assign global master point
825  const globalIndex globalPoints(mesh_.nPoints());
826 
827  const globalMeshData& gmd = mesh_.globalData();
828  const indirectPrimitivePatch& cpp = gmd.coupledPatch();
829  const labelList& meshPoints = cpp.meshPoints();
830  const mapDistribute& slavesMap = gmd.globalCoPointSlavesMap();
831  const labelListList& slaves = gmd.globalCoPointSlaves();
832 
833  labelList elems(slavesMap.constructSize(), -1);
834  forAll(meshPoints, pointi)
835  {
836  const labelList& slots = slaves[pointi];
837 
838  if (slots.size())
839  {
840  // pointi is a master. Assign a unique label.
841 
842  label globalPointi = globalPoints.toGlobal(meshPoints[pointi]);
843  elems[pointi] = globalPointi;
844  forAll(slots, i)
845  {
846  label sloti = slots[i];
847  if (sloti >= meshPoints.size())
848  {
849  // Filter out local collocated points. We don't want
850  // to merge these
851  elems[slots[i]] = globalPointi;
852  }
853  }
854  }
855  }
856 
857  // Push slave-slot data back to slaves
858  slavesMap.reverseDistribute(elems.size(), elems, false);
859 
860  // Extract back onto mesh
861  forAll(meshPoints, pointi)
862  {
863  sourcePointMaster[meshPoints[pointi]] = elems[pointi];
864  }
865  }
866 }
867 
868 
869 // Subset the neighbourCell/neighbourProc fields
870 void Foam::fvMeshDistribute::subsetCouplingData
871 (
872  const fvMesh& mesh,
873  const labelList& pointMap,
874  const labelList& faceMap,
875  const labelList& cellMap,
876 
877  const labelList& oldDistribution,
878  const labelList& oldFaceOwner,
879  const labelList& oldFaceNeighbour,
880  const label oldInternalFaces,
881 
882  const labelList& sourceFace,
883  const labelList& sourceProc,
884  const labelList& sourcePatch,
885  const labelList& sourceNewNbrProc,
886  const labelList& sourcePointMaster,
887 
888  labelList& subFace,
889  labelList& subProc,
890  labelList& subPatch,
891  labelList& subNewNbrProc,
892  labelList& subPointMaster
893 )
894 {
895  subFace.setSize(mesh.nFaces() - mesh.nInternalFaces());
896  subProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
897  subPatch.setSize(mesh.nFaces() - mesh.nInternalFaces());
898  subNewNbrProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
899 
900  forAll(subFace, newBFacei)
901  {
902  label newFacei = newBFacei + mesh.nInternalFaces();
903 
904  label oldFacei = faceMap[newFacei];
905 
906  // Was oldFacei internal face? If so which side did we get.
907  if (oldFacei < oldInternalFaces)
908  {
909  subFace[newBFacei] = oldFacei;
910  subProc[newBFacei] = Pstream::myProcNo();
911  subPatch[newBFacei] = -1;
912 
913  label oldOwn = oldFaceOwner[oldFacei];
914  label oldNei = oldFaceNeighbour[oldFacei];
915 
916  if (oldOwn == cellMap[mesh.faceOwner()[newFacei]])
917  {
918  // We kept the owner side. Where does the neighbour move to?
919  subNewNbrProc[newBFacei] = oldDistribution[oldNei];
920  }
921  else
922  {
923  // We kept the neighbour side.
924  subNewNbrProc[newBFacei] = oldDistribution[oldOwn];
925  }
926  }
927  else
928  {
929  // Was boundary face. Take over boundary information
930  label oldBFacei = oldFacei - oldInternalFaces;
931 
932  subFace[newBFacei] = sourceFace[oldBFacei];
933  subProc[newBFacei] = sourceProc[oldBFacei];
934  subPatch[newBFacei] = sourcePatch[oldBFacei];
935  subNewNbrProc[newBFacei] = sourceNewNbrProc[oldBFacei];
936  }
937  }
938 
939 
940  subPointMaster = UIndirectList<label>(sourcePointMaster, pointMap);
941 }
942 
943 
944 // Find cells on mesh whose faceID/procID match the neighbour cell/proc of
945 // domainMesh. Store the matching face.
946 void Foam::fvMeshDistribute::findCouples
947 (
948  const primitiveMesh& mesh,
949  const labelList& sourceFace,
950  const labelList& sourceProc,
951  const labelList& sourcePatch,
952 
953  const label domain,
954  const primitiveMesh& domainMesh,
955  const labelList& domainFace,
956  const labelList& domainProc,
957  const labelList& domainPatch,
958 
959  labelList& masterCoupledFaces,
960  labelList& slaveCoupledFaces
961 )
962 {
963  // Store domain neighbour as map so we can easily look for pair
964  // with same face+proc.
966 
967  forAll(domainProc, bFacei)
968  {
969  if (domainProc[bFacei] != -1 && domainPatch[bFacei] == -1)
970  {
971  map.insert
972  (
973  labelPair(domainFace[bFacei], domainProc[bFacei]),
974  bFacei
975  );
976  }
977  }
978 
979 
980  // Try to match mesh data.
981 
982  masterCoupledFaces.setSize(domainFace.size());
983  slaveCoupledFaces.setSize(domainFace.size());
984  label coupledI = 0;
985 
986  forAll(sourceFace, bFacei)
987  {
988  if (sourceProc[bFacei] != -1 && sourcePatch[bFacei] == -1)
989  {
990  labelPair myData(sourceFace[bFacei], sourceProc[bFacei]);
991 
993  iter = map.find(myData);
994 
995  if (iter != map.end())
996  {
997  label nbrBFacei = iter();
998 
999  masterCoupledFaces[coupledI] = mesh.nInternalFaces() + bFacei;
1000  slaveCoupledFaces[coupledI] =
1001  domainMesh.nInternalFaces()
1002  + nbrBFacei;
1003 
1004  coupledI++;
1005  }
1006  }
1007  }
1008 
1009  masterCoupledFaces.setSize(coupledI);
1010  slaveCoupledFaces.setSize(coupledI);
1011 
1012  if (debug)
1013  {
1014  Pout<< "findCouples : found " << coupledI
1015  << " faces that will be stitched" << nl << endl;
1016  }
1017 }
1018 
1019 
1020 // Map data on boundary faces to new mesh (resulting from adding two meshes)
1021 Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
1022 (
1023  const primitiveMesh& mesh, // mesh after adding
1024  const mapAddedPolyMesh& map,
1025  const labelList& boundaryData0, // on mesh before adding
1026  const label nInternalFaces1,
1027  const labelList& boundaryData1 // on added mesh
1028 )
1029 {
1030  labelList newBoundaryData(mesh.nFaces() - mesh.nInternalFaces());
1031 
1032  forAll(boundaryData0, oldBFacei)
1033  {
1034  label newFacei = map.oldFaceMap()[oldBFacei + map.nOldInternalFaces()];
1035 
1036  // Face still exists (is necessary?) and still boundary face
1037  if (newFacei >= 0 && newFacei >= mesh.nInternalFaces())
1038  {
1039  newBoundaryData[newFacei - mesh.nInternalFaces()] =
1040  boundaryData0[oldBFacei];
1041  }
1042  }
1043 
1044  forAll(boundaryData1, addedBFacei)
1045  {
1046  label newFacei = map.addedFaceMap()[addedBFacei + nInternalFaces1];
1047 
1048  if (newFacei >= 0 && newFacei >= mesh.nInternalFaces())
1049  {
1050  newBoundaryData[newFacei - mesh.nInternalFaces()] =
1051  boundaryData1[addedBFacei];
1052  }
1053  }
1054 
1055  return newBoundaryData;
1056 }
1057 
1058 
1059 Foam::labelList Foam::fvMeshDistribute::mapPointData
1060 (
1061  const primitiveMesh& mesh, // mesh after adding
1062  const mapAddedPolyMesh& map,
1063  const labelList& boundaryData0, // on mesh before adding
1064  const labelList& boundaryData1 // on added mesh
1065 )
1066 {
1067  labelList newBoundaryData(mesh.nPoints());
1068 
1069  forAll(boundaryData0, oldPointi)
1070  {
1071  label newPointi = map.oldPointMap()[oldPointi];
1072 
1073  // Point still exists (is necessary?)
1074  if (newPointi >= 0)
1075  {
1076  newBoundaryData[newPointi] = boundaryData0[oldPointi];
1077  }
1078  }
1079 
1080  forAll(boundaryData1, addedPointi)
1081  {
1082  label newPointi = map.addedPointMap()[addedPointi];
1083 
1084  if (newPointi >= 0)
1085  {
1086  newBoundaryData[newPointi] = boundaryData1[addedPointi];
1087  }
1088  }
1089 
1090  return newBoundaryData;
1091 }
1092 
1093 
1094 // Remove cells. Add all exposed faces to patch oldInternalPatchi
1095 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
1096 (
1097  const labelList& cellsToRemove,
1098  const label oldInternalPatchi
1099 )
1100 {
1101  // Mesh change engine
1102  polyTopoChange meshMod(mesh_);
1103 
1104  // Cell removal topo engine. Do NOT synchronize parallel since
1105  // we are doing a local cell removal.
1106  removeCells cellRemover(mesh_, false);
1107 
1108  // Get all exposed faces
1109  labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
1110 
1111  // Insert the topo changes
1112  cellRemover.setRefinement
1113  (
1114  cellsToRemove,
1115  exposedFaces,
1116  labelList(exposedFaces.size(), oldInternalPatchi), // patch for exposed
1117  // faces.
1118  meshMod
1119  );
1120 
1121 
1123  // tmp<surfaceScalarField> sfld(generateTestField(mesh_));
1124 
1125  // Save internal fields (note: not as DimensionedFields since would
1126  // get mapped)
1127  PtrList<Field<scalar>> sFlds;
1128  saveInternalFields(sFlds);
1129  PtrList<Field<vector>> vFlds;
1130  saveInternalFields(vFlds);
1132  saveInternalFields(sptFlds);
1133  PtrList<Field<symmTensor>> sytFlds;
1134  saveInternalFields(sytFlds);
1135  PtrList<Field<tensor>> tFlds;
1136  saveInternalFields(tFlds);
1137 
1138  // Change the mesh. No inflation. Note: no parallel comms allowed.
1139  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
1140 
1141  // Update fields
1142  mesh_.updateMesh(map);
1143 
1144 
1145  // Any exposed faces in a surfaceField will not be mapped. Map the value
1146  // of these separately (until there is support in all PatchFields for
1147  // mapping from internal faces ...)
1148 
1149  mapExposedFaces(map(), sFlds);
1150  mapExposedFaces(map(), vFlds);
1151  mapExposedFaces(map(), sptFlds);
1152  mapExposedFaces(map(), sytFlds);
1153  mapExposedFaces(map(), tFlds);
1154 
1155 
1157  // testField(sfld);
1158 
1159 
1160  // Move mesh (since morphing does not do this)
1161  if (map().hasMotionPoints())
1162  {
1163  mesh_.movePoints(map().preMotionPoints());
1164  }
1165 
1166  return map;
1167 }
1168 
1169 
1170 // Delete and add processor patches. Changes mesh and returns per neighbour proc
1171 // the processor patchID.
1172 void Foam::fvMeshDistribute::addProcPatches
1173 (
1174  const labelList& nbrProc, // processor that neighbour is now on
1175  const labelList& referPatchID, // patchID (or -1) I originated from
1176  List<Map<label>>& procPatchID
1177 )
1178 {
1179  // Now use the neighbourFace/Proc to repatch the mesh. These lists
1180  // contain for all current boundary faces the global patchID (for non-proc
1181  // patch) or the processor.
1182 
1183  // Determine a visit order such that the processor patches get added
1184  // in order of increasing neighbour processor (and for same neighbour
1185  // processor (in case of processor cyclics) in order of increasing
1186  // 'refer' patch)
1187  labelList indices;
1188  sortedOrder(nbrProc, indices, lessProcPatches(nbrProc, referPatchID));
1189 
1190  procPatchID.setSize(Pstream::nProcs());
1191 
1192  forAll(indices, i)
1193  {
1194  label bFacei = indices[i];
1195  label proci = nbrProc[bFacei];
1196 
1197  if (proci != -1 && proci != Pstream::myProcNo())
1198  {
1199  if (!procPatchID[proci].found(referPatchID[bFacei]))
1200  {
1201  // No patch for neighbour yet. Is either a normal processor
1202  // patch or a processorCyclic patch.
1203 
1204  if (referPatchID[bFacei] == -1)
1205  {
1206  // Ordinary processor boundary
1207 
1209  (
1210  0, // size
1211  mesh_.nFaces(),
1212  mesh_.boundaryMesh().size(),
1213  mesh_.boundaryMesh(),
1215  proci
1216  );
1217 
1218  procPatchID[proci].insert
1219  (
1220  referPatchID[bFacei],
1222  (
1223  mesh_,
1224  pp,
1225  dictionary(), // optional per field patchField
1227  false // not parallel sync
1228  )
1229  );
1230  }
1231  else
1232  {
1233  const coupledPolyPatch& pcPatch
1234  = refCast<const coupledPolyPatch>
1235  (
1236  mesh_.boundaryMesh()[referPatchID[bFacei]]
1237  );
1239  (
1240  0, // size
1241  mesh_.nFaces(),
1242  mesh_.boundaryMesh().size(),
1243  mesh_.boundaryMesh(),
1245  proci,
1246  pcPatch.name(),
1247  pcPatch.transform()
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  xferMove(domainPoints),
1510  xferMove(domainFaces),
1511  xferMove(domainAllOwner),
1512  xferMove(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
1579 Foam::fvMeshDistribute::fvMeshDistribute(fvMesh& mesh, const scalar mergeTol)
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  oldPatchStarts.xfer(),
1668  oldPatchNMeshPoints.xfer(),
1669 
1670  labelListList(1, identity(mesh_.nPoints())).xfer(),
1671  labelListList(1, identity(mesh_.nFaces())).xfer(),
1672  labelListList(1, identity(mesh_.nCells())).xfer(),
1673  labelListList(1, identity(patches.size())).xfer(),
1674 
1675  labelListList(1, identity(mesh_.nPoints())).xfer(),
1676  labelListList(1, identity(mesh_.nFaces())).xfer(),
1677  labelListList(1, identity(mesh_.nCells())).xfer(),
1678  labelListList(1, identity(patches.size())).xfer()
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  typedef volScalarField::Internal dimScalType;
1785  const wordList dimScalars(mesh_.names(dimScalType::typeName));
1786  checkEqualWordList("volScalarField::Internal", dimScalars);
1787 
1788  typedef volVectorField::Internal dimVecType;
1789  const wordList dimVectors(mesh_.names(dimVecType::typeName));
1790  checkEqualWordList("volVectorField::Internal", dimVectors);
1791 
1792  typedef volSphericalTensorField::Internal dimSphereType;
1793  const wordList dimSphereTensors(mesh_.names(dimSphereType::typeName));
1794  checkEqualWordList
1795  (
1796  "volSphericalTensorField::Internal",
1797  dimSphereTensors
1798  );
1799 
1800  typedef volSymmTensorField::Internal dimSymmTensorType;
1801  const wordList dimSymmTensors(mesh_.names(dimSymmTensorType::typeName));
1802  checkEqualWordList
1803  (
1804  "volSymmTensorField::Internal",
1805  dimSymmTensors
1806  );
1807 
1808  typedef volTensorField::Internal dimTensorType;
1809  const wordList dimTensors(mesh_.names(dimTensorType::typeName));
1810  checkEqualWordList("volTensorField::Internal", dimTensors);
1811 
1812 
1813 
1814  // Find patch to temporarily put exposed and processor faces into.
1815  label oldInternalPatchi = findNonEmptyPatch();
1816 
1817 
1818 
1819  // Delete processor patches, starting from the back. Move all faces into
1820  // oldInternalPatchi.
1821  labelList repatchFaceMap;
1822  {
1823  autoPtr<mapPolyMesh> repatchMap = deleteProcPatches(oldInternalPatchi);
1824 
1825  // Store face map (only face ordering that changed)
1826  repatchFaceMap = repatchMap().faceMap();
1827 
1828  // Reorder all boundary face data (sourceProc, sourceFace etc.)
1829  labelList bFaceMap
1830  (
1832  (
1833  repatchMap().reverseFaceMap(),
1834  mesh_.nFaces() - mesh_.nInternalFaces(),
1835  mesh_.nInternalFaces()
1836  )
1837  - mesh_.nInternalFaces()
1838  );
1839 
1840  inplaceReorder(bFaceMap, sourceFace);
1841  inplaceReorder(bFaceMap, sourceProc);
1842  inplaceReorder(bFaceMap, sourcePatch);
1843  inplaceReorder(bFaceMap, sourceNewNbrProc);
1844  }
1845 
1846 
1847 
1848  // Print a bit.
1849  if (debug)
1850  {
1851  Pout<< nl << "MESH WITH PROC PATCHES DELETED:" << endl;
1852  printMeshInfo(mesh_);
1853  printFieldInfo<volScalarField>(mesh_);
1854  printFieldInfo<volVectorField>(mesh_);
1855  printFieldInfo<volSphericalTensorField>(mesh_);
1856  printFieldInfo<volSymmTensorField>(mesh_);
1857  printFieldInfo<volTensorField>(mesh_);
1858  printFieldInfo<surfaceScalarField>(mesh_);
1859  printFieldInfo<surfaceVectorField>(mesh_);
1860  printFieldInfo<surfaceSphericalTensorField>(mesh_);
1861  printFieldInfo<surfaceSymmTensorField>(mesh_);
1862  printFieldInfo<surfaceTensorField>(mesh_);
1863  Pout<< nl << endl;
1864  }
1865 
1866 
1867 
1868  // Maps from subsetted mesh (that is sent) back to original maps
1869  labelListList subCellMap(Pstream::nProcs());
1870  labelListList subFaceMap(Pstream::nProcs());
1871  labelListList subPointMap(Pstream::nProcs());
1872  labelListList subPatchMap(Pstream::nProcs());
1873  // Maps from subsetted mesh to reconstructed mesh
1874  labelListList constructCellMap(Pstream::nProcs());
1875  labelListList constructFaceMap(Pstream::nProcs());
1876  labelListList constructPointMap(Pstream::nProcs());
1877  labelListList constructPatchMap(Pstream::nProcs());
1878 
1879 
1880 
1881 
1882  // Find out schedule
1883  // ~~~~~~~~~~~~~~~~~
1884 
1885  labelListList nSendCells(Pstream::nProcs());
1886  nSendCells[Pstream::myProcNo()] = countCells(distribution);
1887  Pstream::gatherList(nSendCells);
1888  Pstream::scatterList(nSendCells);
1889 
1890 
1891  // Allocate buffers
1893 
1894 
1895  // What to send to neighbouring domains
1896  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1897 
1898  bool oldParRun = UPstream::parRun();
1899  UPstream::parRun() = false;
1900 
1901  forAll(nSendCells[Pstream::myProcNo()], recvProc)
1902  {
1903  if
1904  (
1905  recvProc != Pstream::myProcNo()
1906  && nSendCells[Pstream::myProcNo()][recvProc] > 0
1907  )
1908  {
1909  // Send to recvProc
1910 
1911  if (debug)
1912  {
1913  Pout<< nl
1914  << "SUBSETTING FOR DOMAIN " << recvProc
1915  << " cells to send:"
1916  << nSendCells[Pstream::myProcNo()][recvProc]
1917  << nl << endl;
1918  }
1919 
1920  // Pstream for sending mesh and fields
1921  // OPstream str(Pstream::commsTypes::blocking, recvProc);
1922  UOPstream str(recvProc, pBufs);
1923 
1924  // Mesh subsetting engine
1925  fvMeshSubset subsetter(mesh_);
1926 
1927  // Subset the cells of the current domain.
1928  subsetter.setLargeCellSubset
1929  (
1930  distribution,
1931  recvProc,
1932  oldInternalPatchi, // oldInternalFaces patch
1933  false // no parallel sync
1934  );
1935 
1936  subCellMap[recvProc] = subsetter.cellMap();
1937  subFaceMap[recvProc] = subsetter.faceFlipMap();
1938  inplaceRenumberWithFlip
1939  (
1940  repatchFaceMap,
1941  false, // oldToNew has flip
1942  true, // subFaceMap has flip
1943  subFaceMap[recvProc]
1944  );
1945  subPointMap[recvProc] = subsetter.pointMap();
1946  subPatchMap[recvProc] = subsetter.patchMap();
1947 
1948 
1949  // Subset the boundary fields (owner/neighbour/processor)
1950  labelList procSourceFace;
1951  labelList procSourceProc;
1952  labelList procSourcePatch;
1953  labelList procSourceNewNbrProc;
1954  labelList procSourcePointMaster;
1955 
1956  subsetCouplingData
1957  (
1958  subsetter.subMesh(),
1959  subsetter.pointMap(), // from subMesh to mesh
1960  subsetter.faceMap(), // ,, ,,
1961  subsetter.cellMap(), // ,, ,,
1962 
1963  distribution, // old mesh distribution
1964  mesh_.faceOwner(), // old owner
1965  mesh_.faceNeighbour(),
1966  mesh_.nInternalFaces(),
1967 
1968  sourceFace,
1969  sourceProc,
1970  sourcePatch,
1971  sourceNewNbrProc,
1972  sourcePointMaster,
1973 
1974  procSourceFace,
1975  procSourceProc,
1976  procSourcePatch,
1977  procSourceNewNbrProc,
1978  procSourcePointMaster
1979  );
1980 
1981 
1982  // Send to neighbour
1983  sendMesh
1984  (
1985  recvProc,
1986  subsetter.subMesh(),
1987 
1988  pointZoneNames,
1989  faceZoneNames,
1990  cellZoneNames,
1991 
1992  procSourceFace,
1993  procSourceProc,
1994  procSourcePatch,
1995  procSourceNewNbrProc,
1996  procSourcePointMaster,
1997 
1998  str
1999  );
2000 
2001  // volFields
2002  sendFields<volScalarField>(recvProc, volScalars, subsetter, str);
2003  sendFields<volVectorField>(recvProc, volVectors, subsetter, str);
2004  sendFields<volSphericalTensorField>
2005  (
2006  recvProc,
2007  volSphereTensors,
2008  subsetter,
2009  str
2010  );
2011  sendFields<volSymmTensorField>
2012  (
2013  recvProc,
2014  volSymmTensors,
2015  subsetter,
2016  str
2017  );
2018  sendFields<volTensorField>(recvProc, volTensors, subsetter, str);
2019 
2020  // surfaceFields
2021  sendFields<surfaceScalarField>
2022  (
2023  recvProc,
2024  surfScalars,
2025  subsetter,
2026  str
2027  );
2028  sendFields<surfaceVectorField>
2029  (
2030  recvProc,
2031  surfVectors,
2032  subsetter,
2033  str
2034  );
2035  sendFields<surfaceSphericalTensorField>
2036  (
2037  recvProc,
2038  surfSphereTensors,
2039  subsetter,
2040  str
2041  );
2042  sendFields<surfaceSymmTensorField>
2043  (
2044  recvProc,
2045  surfSymmTensors,
2046  subsetter,
2047  str
2048  );
2049  sendFields<surfaceTensorField>
2050  (
2051  recvProc,
2052  surfTensors,
2053  subsetter,
2054  str
2055  );
2056 
2057  // dimensionedFields
2058  sendFields<volScalarField::Internal>
2059  (
2060  recvProc,
2061  dimScalars,
2062  subsetter,
2063  str
2064  );
2065  sendFields<volVectorField::Internal>
2066  (
2067  recvProc,
2068  dimVectors,
2069  subsetter,
2070  str
2071  );
2072  sendFields<volSphericalTensorField::Internal>
2073  (
2074  recvProc,
2075  dimSphereTensors,
2076  subsetter,
2077  str
2078  );
2079  sendFields<volSymmTensorField::Internal>
2080  (
2081  recvProc,
2082  dimSymmTensors,
2083  subsetter,
2084  str
2085  );
2086  sendFields<volTensorField::Internal>
2087  (
2088  recvProc,
2089  dimTensors,
2090  subsetter,
2091  str
2092  );
2093  }
2094  }
2095 
2096 
2097  UPstream::parRun() = oldParRun;
2098 
2099 
2100  // Start sending&receiving from buffers
2101  pBufs.finishedSends();
2102 
2103 
2104  // Subset the part that stays
2105  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
2106 
2107  {
2108  // Save old mesh maps before changing mesh
2109  const labelList oldFaceOwner(mesh_.faceOwner());
2110  const labelList oldFaceNeighbour(mesh_.faceNeighbour());
2111  const label oldInternalFaces = mesh_.nInternalFaces();
2112 
2113  // Remove cells.
2114  autoPtr<mapPolyMesh> subMap
2115  (
2116  doRemoveCells
2117  (
2118  select(false, distribution, Pstream::myProcNo()),
2119  oldInternalPatchi
2120  )
2121  );
2122 
2123  // Addressing from subsetted mesh
2124  subCellMap[Pstream::myProcNo()] = subMap().cellMap();
2125  subFaceMap[Pstream::myProcNo()] = renumber
2126  (
2127  repatchFaceMap,
2128  subMap().faceMap()
2129  );
2130  // Insert the sign bit from face flipping
2131  labelList& faceMap = subFaceMap[Pstream::myProcNo()];
2132  forAll(faceMap, faceI)
2133  {
2134  faceMap[faceI] += 1;
2135  }
2136  const labelHashSet& flip = subMap().flipFaceFlux();
2137  forAllConstIter(labelHashSet, flip, iter)
2138  {
2139  label faceI = iter.key();
2140  faceMap[faceI] = -faceMap[faceI];
2141  }
2142  subPointMap[Pstream::myProcNo()] = subMap().pointMap();
2143  subPatchMap[Pstream::myProcNo()] = identity(patches.size());
2144 
2145  // Initialize all addressing into current mesh
2146  constructCellMap[Pstream::myProcNo()] = identity(mesh_.nCells());
2147  constructFaceMap[Pstream::myProcNo()] = identity(mesh_.nFaces()) + 1;
2148  constructPointMap[Pstream::myProcNo()] = identity(mesh_.nPoints());
2149  constructPatchMap[Pstream::myProcNo()] = identity(patches.size());
2150 
2151  // Subset the mesh data: neighbourCell/neighbourProc
2152  // fields
2153  labelList domainSourceFace;
2154  labelList domainSourceProc;
2155  labelList domainSourcePatch;
2156  labelList domainSourceNewNbrProc;
2157  labelList domainSourcePointMaster;
2158 
2159  subsetCouplingData
2160  (
2161  mesh_, // new mesh
2162  subMap().pointMap(), // from new to original mesh
2163  subMap().faceMap(), // from new to original mesh
2164  subMap().cellMap(),
2165 
2166  distribution, // distribution before subsetting
2167  oldFaceOwner, // owner before subsetting
2168  oldFaceNeighbour, // neighbour ,,
2169  oldInternalFaces, // nInternalFaces ,,
2170 
2171  sourceFace,
2172  sourceProc,
2173  sourcePatch,
2174  sourceNewNbrProc,
2175  sourcePointMaster,
2176 
2177  domainSourceFace,
2178  domainSourceProc,
2179  domainSourcePatch,
2180  domainSourceNewNbrProc,
2181  domainSourcePointMaster
2182  );
2183 
2184  sourceFace.transfer(domainSourceFace);
2185  sourceProc.transfer(domainSourceProc);
2186  sourcePatch.transfer(domainSourcePatch);
2187  sourceNewNbrProc.transfer(domainSourceNewNbrProc);
2188  sourcePointMaster.transfer(domainSourcePointMaster);
2189  }
2190 
2191 
2192  // Print a bit.
2193  if (debug)
2194  {
2195  Pout<< nl << "STARTING MESH:" << endl;
2196  printMeshInfo(mesh_);
2197  printFieldInfo<volScalarField>(mesh_);
2198  printFieldInfo<volVectorField>(mesh_);
2199  printFieldInfo<volSphericalTensorField>(mesh_);
2200  printFieldInfo<volSymmTensorField>(mesh_);
2201  printFieldInfo<volTensorField>(mesh_);
2202  printFieldInfo<surfaceScalarField>(mesh_);
2203  printFieldInfo<surfaceVectorField>(mesh_);
2204  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2205  printFieldInfo<surfaceSymmTensorField>(mesh_);
2206  printFieldInfo<surfaceTensorField>(mesh_);
2207  Pout<< nl << endl;
2208  }
2209 
2210 
2211 
2212  // Receive and add what was sent
2213  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2214 
2215  oldParRun = UPstream::parRun();
2216  UPstream::parRun() = false;
2217 
2218  forAll(nSendCells, sendProc)
2219  {
2220  // Did processor sendProc send anything to me?
2221  if
2222  (
2223  sendProc != Pstream::myProcNo()
2224  && nSendCells[sendProc][Pstream::myProcNo()] > 0
2225  )
2226  {
2227  if (debug)
2228  {
2229  Pout<< nl
2230  << "RECEIVING FROM DOMAIN " << sendProc
2231  << " cells to receive:"
2232  << nSendCells[sendProc][Pstream::myProcNo()]
2233  << nl << endl;
2234  }
2235 
2236 
2237  // Pstream for receiving mesh and fields
2238  UIPstream str(sendProc, pBufs);
2239 
2240 
2241  // Receive from sendProc
2242  labelList domainSourceFace;
2243  labelList domainSourceProc;
2244  labelList domainSourcePatch;
2245  labelList domainSourceNewNbrProc;
2246  labelList domainSourcePointMaster;
2247 
2248  autoPtr<fvMesh> domainMeshPtr;
2249 
2255 
2261 
2267 
2268 
2269  // Opposite of sendMesh
2270  {
2271  domainMeshPtr = receiveMesh
2272  (
2273  sendProc,
2274  pointZoneNames,
2275  faceZoneNames,
2276  cellZoneNames,
2277 
2278  const_cast<Time&>(mesh_.time()),
2279  domainSourceFace,
2280  domainSourceProc,
2281  domainSourcePatch,
2282  domainSourceNewNbrProc,
2283  domainSourcePointMaster,
2284  str
2285  );
2286  fvMesh& domainMesh = domainMeshPtr();
2287  // Force construction of various on mesh.
2288  //(void)domainMesh.globalData();
2289 
2290 
2291  // Receive fields. Read as single dictionary because
2292  // of problems reading consecutive fields from single stream.
2293  dictionary fieldDicts(str);
2294 
2295  // Vol fields
2296  receiveFields<volScalarField>
2297  (
2298  sendProc,
2299  volScalars,
2300  domainMesh,
2301  vsf,
2302  fieldDicts.subDict(volScalarField::typeName)
2303  );
2304  receiveFields<volVectorField>
2305  (
2306  sendProc,
2307  volVectors,
2308  domainMesh,
2309  vvf,
2310  fieldDicts.subDict(volVectorField::typeName)
2311  );
2312  receiveFields<volSphericalTensorField>
2313  (
2314  sendProc,
2315  volSphereTensors,
2316  domainMesh,
2317  vsptf,
2319  );
2320  receiveFields<volSymmTensorField>
2321  (
2322  sendProc,
2323  volSymmTensors,
2324  domainMesh,
2325  vsytf,
2327  );
2328  receiveFields<volTensorField>
2329  (
2330  sendProc,
2331  volTensors,
2332  domainMesh,
2333  vtf,
2334  fieldDicts.subDict(volTensorField::typeName)
2335  );
2336 
2337  // Surface fields
2338  receiveFields<surfaceScalarField>
2339  (
2340  sendProc,
2341  surfScalars,
2342  domainMesh,
2343  ssf,
2345  );
2346  receiveFields<surfaceVectorField>
2347  (
2348  sendProc,
2349  surfVectors,
2350  domainMesh,
2351  svf,
2353  );
2354  receiveFields<surfaceSphericalTensorField>
2355  (
2356  sendProc,
2357  surfSphereTensors,
2358  domainMesh,
2359  ssptf,
2361  );
2362  receiveFields<surfaceSymmTensorField>
2363  (
2364  sendProc,
2365  surfSymmTensors,
2366  domainMesh,
2367  ssytf,
2369  );
2370  receiveFields<surfaceTensorField>
2371  (
2372  sendProc,
2373  surfTensors,
2374  domainMesh,
2375  stf,
2377  );
2378 
2379  // Dimensioned fields
2380  receiveFields<volScalarField::Internal>
2381  (
2382  sendProc,
2383  dimScalars,
2384  domainMesh,
2385  dsf,
2386  fieldDicts.subDict
2387  (
2389  )
2390  );
2391  receiveFields<volVectorField::Internal>
2392  (
2393  sendProc,
2394  dimVectors,
2395  domainMesh,
2396  dvf,
2397  fieldDicts.subDict
2398  (
2400  )
2401  );
2402  receiveFields<volSphericalTensorField::Internal>
2403  (
2404  sendProc,
2405  dimSphereTensors,
2406  domainMesh,
2407  dstf,
2408  fieldDicts.subDict
2409  (
2411  typeName
2412  )
2413  );
2414  receiveFields<volSymmTensorField::Internal>
2415  (
2416  sendProc,
2417  dimSymmTensors,
2418  domainMesh,
2419  dsytf,
2420  fieldDicts.subDict
2421  (
2423  )
2424  );
2425  receiveFields<volTensorField::Internal>
2426  (
2427  sendProc,
2428  dimTensors,
2429  domainMesh,
2430  dtf,
2431  fieldDicts.subDict
2432  (
2434  )
2435  );
2436  }
2437  const fvMesh& domainMesh = domainMeshPtr();
2438 
2439 
2440  constructCellMap[sendProc] = identity(domainMesh.nCells());
2441  constructFaceMap[sendProc] = identity(domainMesh.nFaces()) + 1;
2442  constructPointMap[sendProc] = identity(domainMesh.nPoints());
2443  constructPatchMap[sendProc] =
2444  identity(domainMesh.boundaryMesh().size());
2445 
2446 
2447  // Print a bit.
2448  if (debug)
2449  {
2450  Pout<< nl << "RECEIVED MESH FROM:" << sendProc << endl;
2451  printMeshInfo(domainMesh);
2452  printFieldInfo<volScalarField>(domainMesh);
2453  printFieldInfo<volVectorField>(domainMesh);
2454  printFieldInfo<volSphericalTensorField>(domainMesh);
2455  printFieldInfo<volSymmTensorField>(domainMesh);
2456  printFieldInfo<volTensorField>(domainMesh);
2457  printFieldInfo<surfaceScalarField>(domainMesh);
2458  printFieldInfo<surfaceVectorField>(domainMesh);
2459  printFieldInfo<surfaceSphericalTensorField>(domainMesh);
2460  printFieldInfo<surfaceSymmTensorField>(domainMesh);
2461  printFieldInfo<surfaceTensorField>(domainMesh);
2462  }
2463 
2464 
2465  // Now this mesh we received (from sendProc) needs to be merged
2466  // with the current mesh. On the current mesh we have for all
2467  // boundaryfaces the original face and processor. See if we can
2468  // match these up to the received domainSourceFace and
2469  // domainSourceProc.
2470  labelList masterCoupledFaces;
2471  labelList slaveCoupledFaces;
2472  findCouples
2473  (
2474  mesh_,
2475 
2476  sourceFace,
2477  sourceProc,
2478  sourcePatch,
2479 
2480  sendProc,
2481  domainMesh,
2482  domainSourceFace,
2483  domainSourceProc,
2484  domainSourcePatch,
2485 
2486  masterCoupledFaces,
2487  slaveCoupledFaces
2488  );
2489 
2490  // Generate additional coupling info (points, edges) from
2491  // faces-that-match
2492  faceCoupleInfo couples
2493  (
2494  mesh_,
2495  masterCoupledFaces,
2496  domainMesh,
2497  slaveCoupledFaces,
2498  mergeTol_, // merge tolerance
2499  true, // faces align
2500  true, // couples are ordered already
2501  false
2502  );
2503 
2504 
2505  // Add domainMesh to mesh
2506  // ~~~~~~~~~~~~~~~~~~~~~~
2507 
2509  (
2510  mesh_,
2511  domainMesh,
2512  couples,
2513  false // no parallel comms
2514  );
2515 
2516  // Update mesh data: sourceFace,sourceProc for added
2517  // mesh.
2518 
2519  sourceFace = mapBoundaryData
2520  (
2521  mesh_,
2522  map(),
2523  sourceFace,
2524  domainMesh.nInternalFaces(),
2525  domainSourceFace
2526  );
2527  sourceProc = mapBoundaryData
2528  (
2529  mesh_,
2530  map(),
2531  sourceProc,
2532  domainMesh.nInternalFaces(),
2533  domainSourceProc
2534  );
2535  sourcePatch = mapBoundaryData
2536  (
2537  mesh_,
2538  map(),
2539  sourcePatch,
2540  domainMesh.nInternalFaces(),
2541  domainSourcePatch
2542  );
2543  sourceNewNbrProc = mapBoundaryData
2544  (
2545  mesh_,
2546  map(),
2547  sourceNewNbrProc,
2548  domainMesh.nInternalFaces(),
2549  domainSourceNewNbrProc
2550  );
2551  // Update pointMaster data
2552  sourcePointMaster = mapPointData
2553  (
2554  mesh_,
2555  map(),
2556  sourcePointMaster,
2557  domainSourcePointMaster
2558  );
2559 
2560 
2561  // Update all addressing so xxProcAddressing points to correct
2562  // item in masterMesh.
2563  const labelList& oldCellMap = map().oldCellMap();
2564  const labelList& oldFaceMap = map().oldFaceMap();
2565  const labelList& oldPointMap = map().oldPointMap();
2566  const labelList& oldPatchMap = map().oldPatchMap();
2567 
2568  // Note: old mesh faces never flipped!
2569  forAll(constructPatchMap, proci)
2570  {
2571  if (proci != sendProc && constructPatchMap[proci].size())
2572  {
2573  // Processor already in mesh (either myProcNo or received)
2574  inplaceRenumber(oldCellMap, constructCellMap[proci]);
2575  inplaceRenumberWithFlip
2576  (
2577  oldFaceMap,
2578  false,
2579  true,
2580  constructFaceMap[proci]
2581  );
2582  inplaceRenumber(oldPointMap, constructPointMap[proci]);
2583  inplaceRenumber(oldPatchMap, constructPatchMap[proci]);
2584  }
2585  }
2586 
2587 
2588  labelHashSet flippedAddedFaces;
2589  {
2590  // Find out if any faces of domain mesh were flipped (boundary
2591  // faces becoming internal)
2592  label nBnd = domainMesh.nFaces()-domainMesh.nInternalFaces();
2593  flippedAddedFaces.resize(nBnd/4);
2594 
2595  for
2596  (
2597  label domainFaceI = domainMesh.nInternalFaces();
2598  domainFaceI < domainMesh.nFaces();
2599  domainFaceI++
2600  )
2601  {
2602  label newFaceI = map().addedFaceMap()[domainFaceI];
2603  label newCellI = mesh_.faceOwner()[newFaceI];
2604 
2605  label domainCellI = domainMesh.faceOwner()[domainFaceI];
2606 
2607  if (newCellI != map().addedCellMap()[domainCellI])
2608  {
2609  flippedAddedFaces.insert(domainFaceI);
2610  }
2611  }
2612  }
2613 
2614 
2615  // Added processor
2616  inplaceRenumber(map().addedCellMap(), constructCellMap[sendProc]);
2617  // Add flip
2618  forAllConstIter(labelHashSet, flippedAddedFaces, iter)
2619  {
2620  label domainFaceI = iter.key();
2621  label& val = constructFaceMap[sendProc][domainFaceI];
2622  val = -val;
2623  }
2624  inplaceRenumberWithFlip
2625  (
2626  map().addedFaceMap(),
2627  false,
2628  true, // constructFaceMap has flip sign
2629  constructFaceMap[sendProc]
2630  );
2631  inplaceRenumber(map().addedPointMap(), constructPointMap[sendProc]);
2632  inplaceRenumber(map().addedPatchMap(), constructPatchMap[sendProc]);
2633 
2634  if (debug)
2635  {
2636  Pout<< nl << "MERGED MESH FROM:" << sendProc << endl;
2637  printMeshInfo(mesh_);
2638  printFieldInfo<volScalarField>(mesh_);
2639  printFieldInfo<volVectorField>(mesh_);
2640  printFieldInfo<volSphericalTensorField>(mesh_);
2641  printFieldInfo<volSymmTensorField>(mesh_);
2642  printFieldInfo<volTensorField>(mesh_);
2643  printFieldInfo<surfaceScalarField>(mesh_);
2644  printFieldInfo<surfaceVectorField>(mesh_);
2645  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2646  printFieldInfo<surfaceSymmTensorField>(mesh_);
2647  printFieldInfo<surfaceTensorField>(mesh_);
2648  Pout<< nl << endl;
2649  }
2650  }
2651  }
2652 
2653  UPstream::parRun() = oldParRun;
2654 
2655  // Print a bit.
2656  if (debug)
2657  {
2658  Pout<< nl << "REDISTRIBUTED MESH:" << endl;
2659  printMeshInfo(mesh_);
2660  printFieldInfo<volScalarField>(mesh_);
2661  printFieldInfo<volVectorField>(mesh_);
2662  printFieldInfo<volSphericalTensorField>(mesh_);
2663  printFieldInfo<volSymmTensorField>(mesh_);
2664  printFieldInfo<volTensorField>(mesh_);
2665  printFieldInfo<surfaceScalarField>(mesh_);
2666  printFieldInfo<surfaceVectorField>(mesh_);
2667  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2668  printFieldInfo<surfaceSymmTensorField>(mesh_);
2669  printFieldInfo<surfaceTensorField>(mesh_);
2670  Pout<< nl << endl;
2671  }
2672 
2673 
2674  // See if any originally shared points need to be merged. Note: does
2675  // parallel comms. After this points and edges should again be consistent.
2676  mergeSharedPoints(sourcePointMaster, constructPointMap);
2677 
2678 
2679  // Add processorPatches
2680  // ~~~~~~~~~~~~~~~~~~~~
2681 
2682  // Per neighbour processor, per originating patch, the patchID
2683  // For faces resulting from internal faces or normal processor patches
2684  // the originating patch is -1. For cyclics this is the cyclic patchID.
2685  List<Map<label>> procPatchID;
2686 
2687  // Add processor and processorCyclic patches.
2688  addProcPatches(sourceNewNbrProc, sourcePatch, procPatchID);
2689 
2690  // Put faces into correct patch. Note that we now have proper
2691  // processorPolyPatches again so repatching will take care of coupled face
2692  // ordering.
2693 
2694  // Get boundary faces to be repatched. Is -1 or new patchID
2695  labelList newPatchID
2696  (
2697  getBoundaryPatch
2698  (
2699  sourceNewNbrProc,
2700  sourcePatch,
2701  procPatchID
2702  )
2703  );
2704 
2705  // Change patches. Since this might change ordering of coupled faces
2706  // we also need to adapt our constructMaps.
2707  repatch(newPatchID, constructFaceMap);
2708 
2709  // Bit of hack: processorFvPatchField does not get reset since created
2710  // from nothing so explicitly reset.
2711  initPatchFields<volScalarField, processorFvPatchField<scalar>>
2712  (
2713  Zero
2714  );
2715  initPatchFields<volVectorField, processorFvPatchField<vector>>
2716  (
2717  Zero
2718  );
2719  initPatchFields
2720  <
2723  >
2724  (
2725  Zero
2726  );
2727  initPatchFields<volSymmTensorField, processorFvPatchField<symmTensor>>
2728  (
2729  Zero
2730  );
2731  initPatchFields<volTensorField, processorFvPatchField<tensor>>
2732  (
2733  Zero
2734  );
2735 
2736 
2737  mesh_.setInstance(mesh_.time().timeName());
2738 
2739 
2740  // Print a bit
2741  if (debug)
2742  {
2743  Pout<< nl << "FINAL MESH:" << endl;
2744  printMeshInfo(mesh_);
2745  printFieldInfo<volScalarField>(mesh_);
2746  printFieldInfo<volVectorField>(mesh_);
2747  printFieldInfo<volSphericalTensorField>(mesh_);
2748  printFieldInfo<volSymmTensorField>(mesh_);
2749  printFieldInfo<volTensorField>(mesh_);
2750  printFieldInfo<surfaceScalarField>(mesh_);
2751  printFieldInfo<surfaceVectorField>(mesh_);
2752  printFieldInfo<surfaceSphericalTensorField>(mesh_);
2753  printFieldInfo<surfaceSymmTensorField>(mesh_);
2754  printFieldInfo<surfaceTensorField>(mesh_);
2755  Pout<< nl << endl;
2756  }
2757 
2758  // Collect all maps and return
2760  (
2762  (
2763  mesh_,
2764 
2765  nOldPoints,
2766  nOldFaces,
2767  nOldCells,
2768  oldPatchStarts.xfer(),
2769  oldPatchNMeshPoints.xfer(),
2770 
2771  subPointMap.xfer(),
2772  subFaceMap.xfer(),
2773  subCellMap.xfer(),
2774  subPatchMap.xfer(),
2775 
2776  constructPointMap.xfer(),
2777  constructFaceMap.xfer(),
2778  constructCellMap.xfer(),
2779  constructPatchMap.xfer(),
2780 
2781  true, // subFaceMap has flip
2782  true // constructFaceMap has flip
2783  )
2784  );
2785 }
2786 
2787 
2788 // ************************************************************************* //
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:424
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
void clearOut()
Clear all geometry and addressing.
Definition: fvMesh.C:230
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:324
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:428
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:297
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:466
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:110
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:137
void addFvPatches(const List< polyPatch *> &, const bool validBoundary=true)
Add boundary patches. Constructor helper.
Definition: fvMesh.C:460
#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:1047
Xfer< List< T > > xfer()
Transfer contents to the Xfer container.
Definition: ListI.H:177
static const char *const typeName
Definition: Field.H:94
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:74
void resetMotion() const
Reset motion.
Definition: polyMesh.C:1167
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:163
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:253
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:427
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:256
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:440
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:626
patches[0]
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:243
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:116
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:57
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...
Neighbour processor patch.
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1003
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:692
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
Xfer< HashTable< T, Key, Hash > > xfer()
Transfer contents to the Xfer container.
Definition: HashTableI.H:102
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:310
bool operator()(const label a, const label b)
const labelUList & faceCells() const
Return face-cell addressing.
Definition: polyPatch.C:315
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.
Xfer< T > xferMove(T &)
Construct by transferring the contents of the arg.
const pointZoneMesh & pointZones() const
Return point zone mesh.
Definition: polyMesh.H:460
label nOldInternalFaces() const
Number of old internal faces.
const cellZoneMesh & cellZones() const
Return cell zone mesh.
Definition: polyMesh.H:472
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:32
Cyclic plane patch.
wordList names() const
Return a list of patch names.
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1041
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:1028
int neighbProcNo() const
Return neighbour processor number.
An STL-conforming hash table.
Definition: HashTable.H:62
void addZones(const List< pointZone *> &pz, const List< faceZone *> &fz, const List< cellZone *> &cz)
Add mesh zones.
Definition: polyMesh.C:946
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:61
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:53
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:265
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:397
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:409
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:63
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:300
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
virtual transformType transform() const
Type of transform.
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:545