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