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