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