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