domainDecomposition.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "domainDecomposition.H"
30 #include "dictionary.H"
31 #include "labelIOList.H"
32 #include "processorPolyPatch.H"
34 #include "fvMesh.H"
35 #include "OSspecific.H"
36 #include "Map.H"
37 #include "DynamicList.H"
38 #include "fvFieldDecomposer.H"
39 #include "IOobjectList.H"
40 #include "cellSet.H"
41 #include "faceSet.H"
42 #include "pointSet.H"
43 #include "decompositionModel.H"
44 #include "hexRef8Data.H"
45 
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47 
48 void Foam::domainDecomposition::mark
49 (
50  const labelList& zoneElems,
51  const label zoneI,
52  labelList& elementToZone
53 )
54 {
55  for (const label pointi : zoneElems)
56  {
57  if (elementToZone[pointi] == -1)
58  {
59  // First occurrence
60  elementToZone[pointi] = zoneI;
61  }
62  else if (elementToZone[pointi] >= 0)
63  {
64  // Multiple zones
65  elementToZone[pointi] = -2;
66  }
67  }
68 }
69 
70 
71 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
72 
74 (
75  const IOobject& io,
76  const fileName& decompDictFile
77 )
78 :
79  fvMesh(io),
80  facesInstancePointsPtr_
81  (
82  pointsInstance() != facesInstance()
83  ? new pointIOField
84  (
85  IOobject
86  (
87  "points",
88  facesInstance(),
89  polyMesh::meshSubDir,
90  *this,
91  IOobject::MUST_READ,
92  IOobject::NO_WRITE,
93  false
94  )
95  )
96  : nullptr
97  ),
98  decompDictFile_(decompDictFile),
99  nProcs_
100  (
101  decompositionMethod::nDomains
102  (
103  decompositionModel::New
104  (
105  *this,
106  decompDictFile
107  )
108  )
109  ),
110  distributed_(false),
111  cellToProc_(nCells()),
112  procPointAddressing_(nProcs_),
113  procFaceAddressing_(nProcs_),
114  procCellAddressing_(nProcs_),
115  procPatchSize_(nProcs_),
116  procPatchStartIndex_(nProcs_),
117  procNeighbourProcessors_(nProcs_),
118  procProcessorPatchSize_(nProcs_),
119  procProcessorPatchStartIndex_(nProcs_),
120  procProcessorPatchSubPatchIDs_(nProcs_),
121  procProcessorPatchSubPatchStarts_(nProcs_)
122 {
124  (
125  *this,
126  decompDictFile
127  ).readIfPresent("distributed", distributed_);
128 }
129 
130 
131 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
132 
133 bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
134 {
135  Info<< "\nConstructing processor meshes" << endl;
136 
137  // Mark point/faces/cells that are in zones.
138  // -1 : not in zone
139  // -2 : in multiple zones
140  // >= 0 : in single given zone
141  // This will give direct lookup of elements that are in a single zone
142  // and we'll only have to revert back to searching through all zones
143  // for the duplicate elements
144 
145  // Point zones
146  labelList pointToZone(points().size(), -1);
147 
148  forAll(pointZones(), zonei)
149  {
150  mark(pointZones()[zonei], zonei, pointToZone);
151  }
152 
153  // Face zones
154  labelList faceToZone(faces().size(), -1);
155 
156  forAll(faceZones(), zonei)
157  {
158  mark(faceZones()[zonei], zonei, faceToZone);
159  }
160 
161  // Cell zones
162  labelList cellToZone(nCells(), -1);
163 
164  forAll(cellZones(), zonei)
165  {
166  mark(cellZones()[zonei], zonei, cellToZone);
167  }
168 
169 
170  PtrList<const cellSet> cellSets;
171  PtrList<const faceSet> faceSets;
172  PtrList<const pointSet> pointSets;
173  if (decomposeSets)
174  {
175  // Read sets
176  IOobjectList objects(*this, facesInstance(), "polyMesh/sets");
177  {
178  IOobjectList cSets(objects.lookupClass(cellSet::typeName));
179  forAllConstIters(cSets, iter)
180  {
181  cellSets.append(new cellSet(*iter()));
182  }
183  }
184  {
185  IOobjectList fSets(objects.lookupClass(faceSet::typeName));
186  forAllConstIters(fSets, iter)
187  {
188  faceSets.append(new faceSet(*iter()));
189  }
190  }
191  {
192  IOobjectList pSets(objects.lookupClass(pointSet::typeName));
193  forAllConstIters(pSets, iter)
194  {
195  pointSets.append(new pointSet(*iter()));
196  }
197  }
198  }
199 
200 
201  // Load refinement data (if any)
202  hexRef8Data baseMeshData
203  (
204  IOobject
205  (
206  "dummy",
207  facesInstance(),
209  *this,
212  false
213  )
214  );
215 
216 
217 
218  label maxProcCells = 0;
219  label totProcFaces = 0;
220  label maxProcPatches = 0;
221  label totProcPatches = 0;
222  label maxProcFaces = 0;
223 
224 
225  // Write out the meshes
226  for (label proci = 0; proci < nProcs_; proci++)
227  {
228  // Create processor points
229  const labelList& curPointLabels = procPointAddressing_[proci];
230 
231  const pointField& meshPoints = points();
232 
233  labelList pointLookup(nPoints(), -1);
234 
235  pointField procPoints(curPointLabels.size());
236 
237  forAll(curPointLabels, pointi)
238  {
239  procPoints[pointi] = meshPoints[curPointLabels[pointi]];
240 
241  pointLookup[curPointLabels[pointi]] = pointi;
242  }
243 
244  // Create processor faces
245  const labelList& curFaceLabels = procFaceAddressing_[proci];
246 
247  const faceList& meshFaces = faces();
248 
249  labelList faceLookup(nFaces(), -1);
250 
251  faceList procFaces(curFaceLabels.size());
252 
253  forAll(curFaceLabels, facei)
254  {
255  // Mark the original face as used
256  // Remember to decrement the index by one (turning index)
257  //
258  label curF = mag(curFaceLabels[facei]) - 1;
259 
260  faceLookup[curF] = facei;
261 
262  // get the original face
263  labelList origFaceLabels;
264 
265  if (curFaceLabels[facei] >= 0)
266  {
267  // face not turned
268  origFaceLabels = meshFaces[curF];
269  }
270  else
271  {
272  origFaceLabels = meshFaces[curF].reverseFace();
273  }
274 
275  // translate face labels into local point list
276  face& procFaceLabels = procFaces[facei];
277 
278  procFaceLabels.setSize(origFaceLabels.size());
279 
280  forAll(origFaceLabels, pointi)
281  {
282  procFaceLabels[pointi] = pointLookup[origFaceLabels[pointi]];
283  }
284  }
285 
286  // Create processor cells
287  const labelList& curCellLabels = procCellAddressing_[proci];
288 
289  const cellList& meshCells = cells();
290 
291  cellList procCells(curCellLabels.size());
292 
293  forAll(curCellLabels, celli)
294  {
295  const labelList& origCellLabels = meshCells[curCellLabels[celli]];
296 
297  cell& curCell = procCells[celli];
298 
299  curCell.setSize(origCellLabels.size());
300 
301  forAll(origCellLabels, cellFacei)
302  {
303  curCell[cellFacei] = faceLookup[origCellLabels[cellFacei]];
304  }
305  }
306 
307  // Create processor mesh without a boundary
308 
309  fileName processorCasePath
310  (
311  time().caseName()/("processor" + Foam::name(proci))
312  );
313 
314  // create a database
315  Time processorDb
316  (
318  time().rootPath(),
319  processorCasePath,
320  word("system"),
321  word("constant")
322  );
323  processorDb.setTime(time());
324 
325  // create the mesh. Two situations:
326  // - points and faces come from the same time ('instance'). The mesh
327  // will get constructed in the same instance.
328  // - points come from a different time (moving mesh cases).
329  // It will read the points belonging to the faces instance and
330  // construct the procMesh with it which then gets handled as above.
331  // (so with 'old' geometry).
332  // Only at writing time will it additionally write the current
333  // points.
334 
335  autoPtr<polyMesh> procMeshPtr;
336 
337  if (facesInstancePointsPtr_)
338  {
339  // Construct mesh from facesInstance.
340  pointField facesInstancePoints
341  (
342  facesInstancePointsPtr_(),
343  curPointLabels
344  );
345 
346  procMeshPtr = autoPtr<polyMesh>::New
347  (
348  IOobject
349  (
350  this->polyMesh::name(), // region of undecomposed mesh
351  facesInstance(),
352  processorDb,
355  ),
356  std::move(facesInstancePoints),
357  std::move(procFaces),
358  std::move(procCells)
359  );
360  }
361  else
362  {
363  procMeshPtr = autoPtr<polyMesh>::New
364  (
365  IOobject
366  (
367  this->polyMesh::name(), // region of undecomposed mesh
368  facesInstance(),
369  processorDb,
372  ),
373  std::move(procPoints),
374  std::move(procFaces),
375  std::move(procCells)
376  );
377  }
378  polyMesh& procMesh = procMeshPtr();
379 
380 
381  // Create processor boundary patches
382  const labelList& curPatchSizes = procPatchSize_[proci];
383 
384  const labelList& curPatchStarts = procPatchStartIndex_[proci];
385 
386  const labelList& curNeighbourProcessors =
387  procNeighbourProcessors_[proci];
388 
389  const labelList& curProcessorPatchSizes =
390  procProcessorPatchSize_[proci];
391 
392  const labelList& curProcessorPatchStarts =
393  procProcessorPatchStartIndex_[proci];
394 
395  const labelListList& curSubPatchIDs =
396  procProcessorPatchSubPatchIDs_[proci];
397 
398  const labelListList& curSubStarts =
399  procProcessorPatchSubPatchStarts_[proci];
400 
401  const polyPatchList& meshPatches = boundaryMesh();
402 
403 
404  // Count the number of inter-proc patches
405  label nInterProcPatches = 0;
406  forAll(curSubPatchIDs, procPatchi)
407  {
408  nInterProcPatches += curSubPatchIDs[procPatchi].size();
409  }
410 
411  List<polyPatch*> procPatches
412  (
413  curPatchSizes.size() + nInterProcPatches,
414  reinterpret_cast<polyPatch*>(0)
415  );
416 
417  label nPatches = 0;
418 
419  forAll(curPatchSizes, patchi)
420  {
421  // Get the face labels consistent with the field mapping
422  // (reuse the patch field mappers)
423  const polyPatch& meshPatch = meshPatches[patchi];
424 
425  fvFieldDecomposer::patchFieldDecomposer patchMapper
426  (
427  SubList<label>
428  (
429  curFaceLabels,
430  curPatchSizes[patchi],
431  curPatchStarts[patchi]
432  ),
433  meshPatch.start()
434  );
435 
436  // Map existing patches
437  procPatches[nPatches] = meshPatch.clone
438  (
439  procMesh.boundaryMesh(),
440  nPatches,
441  patchMapper.directAddressing(),
442  curPatchStarts[patchi]
443  ).ptr();
444 
445  nPatches++;
446  }
447 
448  forAll(curProcessorPatchSizes, procPatchi)
449  {
450  const labelList& subPatchID = curSubPatchIDs[procPatchi];
451  const labelList& subStarts = curSubStarts[procPatchi];
452 
453  label curStart = curProcessorPatchStarts[procPatchi];
454 
455  forAll(subPatchID, i)
456  {
457  label size =
458  (
459  i < subPatchID.size()-1
460  ? subStarts[i+1] - subStarts[i]
461  : curProcessorPatchSizes[procPatchi] - subStarts[i]
462  );
463 
464  if (subPatchID[i] == -1)
465  {
466  // From internal faces
467  procPatches[nPatches] =
468  new processorPolyPatch
469  (
470  size,
471  curStart,
472  nPatches,
473  procMesh.boundaryMesh(),
474  proci,
475  curNeighbourProcessors[procPatchi]
476  );
477  }
478  else
479  {
480  const coupledPolyPatch& pcPatch
481  = refCast<const coupledPolyPatch>
482  (
483  boundaryMesh()[subPatchID[i]]
484  );
485 
486  procPatches[nPatches] =
487  new processorCyclicPolyPatch
488  (
489  size,
490  curStart,
491  nPatches,
492  procMesh.boundaryMesh(),
493  proci,
494  curNeighbourProcessors[procPatchi],
495  pcPatch.name(),
496  pcPatch.transform()
497  );
498  }
499 
500  curStart += size;
501 
502  nPatches++;
503  }
504  }
505 
506  // Add boundary patches
507  procMesh.addPatches(procPatches);
508 
509  // Create and add zones
510 
511  // Point zones
512  {
513  const pointZoneMesh& pz = pointZones();
514 
515  // Go through all the zoned points and find out if they
516  // belong to a zone. If so, add it to the zone as
517  // necessary
518  List<DynamicList<label>> zonePoints(pz.size());
519 
520  // Estimate size
521  forAll(zonePoints, zonei)
522  {
523  zonePoints[zonei].setCapacity(pz[zonei].size()/nProcs_);
524  }
525 
526  // Use the pointToZone map to find out the single zone (if any),
527  // use slow search only for shared points.
528  forAll(curPointLabels, pointi)
529  {
530  label curPoint = curPointLabels[pointi];
531 
532  label zonei = pointToZone[curPoint];
533 
534  if (zonei >= 0)
535  {
536  // Single zone.
537  zonePoints[zonei].append(pointi);
538  }
539  else if (zonei == -2)
540  {
541  // Multiple zones. Lookup.
542  forAll(pz, zonei)
543  {
544  label index = pz[zonei].whichPoint(curPoint);
545 
546  if (index != -1)
547  {
548  zonePoints[zonei].append(pointi);
549  }
550  }
551  }
552  }
553 
554  procMesh.pointZones().clearAddressing();
555  procMesh.pointZones().setSize(zonePoints.size());
556  forAll(zonePoints, zonei)
557  {
558  procMesh.pointZones().set
559  (
560  zonei,
561  pz[zonei].clone
562  (
563  procMesh.pointZones(),
564  zonei,
565  zonePoints[zonei].shrink()
566  )
567  );
568  }
569 
570  if (pz.size())
571  {
572  // Force writing on all processors
573  procMesh.pointZones().writeOpt() = IOobject::AUTO_WRITE;
574  }
575  }
576 
577  // Face zones
578  {
579  const faceZoneMesh& fz = faceZones();
580 
581  // Go through all the zoned face and find out if they
582  // belong to a zone. If so, add it to the zone as
583  // necessary
584  List<DynamicList<label>> zoneFaces(fz.size());
585  List<DynamicList<bool>> zoneFaceFlips(fz.size());
586 
587  // Estimate size
588  forAll(zoneFaces, zonei)
589  {
590  label procSize = fz[zonei].size() / nProcs_;
591 
592  zoneFaces[zonei].setCapacity(procSize);
593  zoneFaceFlips[zonei].setCapacity(procSize);
594  }
595 
596  // Go through all the zoned faces and find out if they
597  // belong to a zone. If so, add it to the zone as
598  // necessary
599  forAll(curFaceLabels, facei)
600  {
601  // Remember to decrement the index by one (turning index)
602  //
603  label curF = mag(curFaceLabels[facei]) - 1;
604 
605  label zonei = faceToZone[curF];
606 
607  if (zonei >= 0)
608  {
609  // Single zone. Add the face
610  zoneFaces[zonei].append(facei);
611 
612  label index = fz[zonei].whichFace(curF);
613 
614  bool flip = fz[zonei].flipMap()[index];
615 
616  if (curFaceLabels[facei] < 0)
617  {
618  flip = !flip;
619  }
620 
621  zoneFaceFlips[zonei].append(flip);
622  }
623  else if (zonei == -2)
624  {
625  // Multiple zones. Lookup.
626  forAll(fz, zonei)
627  {
628  label index = fz[zonei].whichFace(curF);
629 
630  if (index != -1)
631  {
632  zoneFaces[zonei].append(facei);
633 
634  bool flip = fz[zonei].flipMap()[index];
635 
636  if (curFaceLabels[facei] < 0)
637  {
638  flip = !flip;
639  }
640 
641  zoneFaceFlips[zonei].append(flip);
642  }
643  }
644  }
645  }
646 
647  procMesh.faceZones().clearAddressing();
648  procMesh.faceZones().setSize(zoneFaces.size());
649  forAll(zoneFaces, zonei)
650  {
651  procMesh.faceZones().set
652  (
653  zonei,
654  fz[zonei].clone
655  (
656  zoneFaces[zonei].shrink(), // addressing
657  zoneFaceFlips[zonei].shrink(), // flipmap
658  zonei,
659  procMesh.faceZones()
660  )
661  );
662  }
663 
664  if (fz.size())
665  {
666  // Force writing on all processors
667  procMesh.faceZones().writeOpt() = IOobject::AUTO_WRITE;
668  }
669  }
670 
671  // Cell zones
672  {
673  const cellZoneMesh& cz = cellZones();
674 
675  // Go through all the zoned cells and find out if they
676  // belong to a zone. If so, add it to the zone as
677  // necessary
678  List<DynamicList<label>> zoneCells(cz.size());
679 
680  // Estimate size
681  forAll(zoneCells, zonei)
682  {
683  zoneCells[zonei].setCapacity(cz[zonei].size()/nProcs_);
684  }
685 
686  forAll(curCellLabels, celli)
687  {
688  label curCelli = curCellLabels[celli];
689 
690  label zonei = cellToZone[curCelli];
691 
692  if (zonei >= 0)
693  {
694  // Single zone.
695  zoneCells[zonei].append(celli);
696  }
697  else if (zonei == -2)
698  {
699  // Multiple zones. Lookup.
700  forAll(cz, zonei)
701  {
702  label index = cz[zonei].whichCell(curCelli);
703 
704  if (index != -1)
705  {
706  zoneCells[zonei].append(celli);
707  }
708  }
709  }
710  }
711 
712  procMesh.cellZones().clearAddressing();
713  procMesh.cellZones().setSize(zoneCells.size());
714  forAll(zoneCells, zonei)
715  {
716  procMesh.cellZones().set
717  (
718  zonei,
719  cz[zonei].clone
720  (
721  zoneCells[zonei].shrink(),
722  zonei,
723  procMesh.cellZones()
724  )
725  );
726  }
727 
728  if (cz.size())
729  {
730  // Force writing on all processors
731  procMesh.cellZones().writeOpt() = IOobject::AUTO_WRITE;
732  }
733  }
734 
735  // Set the precision of the points data to be min 10
737 
738  procMesh.write();
739 
740  // Write points if pointsInstance differing from facesInstance
741  if (facesInstancePointsPtr_)
742  {
743  pointIOField pointsInstancePoints
744  (
745  IOobject
746  (
747  "points",
748  pointsInstance(),
750  procMesh,
753  false
754  ),
755  std::move(procPoints)
756  );
757  pointsInstancePoints.write();
758  }
759 
760 
761  // Decompose any sets
762  if (decomposeSets)
763  {
764  forAll(cellSets, i)
765  {
766  const cellSet& cs = cellSets[i];
767  cellSet set(procMesh, cs.name(), cs.size()/nProcs_);
768  forAll(curCellLabels, i)
769  {
770  if (cs.found(curCellLabels[i]))
771  {
772  set.insert(i);
773  }
774  }
775  set.write();
776  }
777  forAll(faceSets, i)
778  {
779  const faceSet& cs = faceSets[i];
780  faceSet set(procMesh, cs.name(), cs.size()/nProcs_);
781  forAll(curFaceLabels, i)
782  {
783  if (cs.found(mag(curFaceLabels[i])-1))
784  {
785  set.insert(i);
786  }
787  }
788  set.write();
789  }
790  forAll(pointSets, i)
791  {
792  const pointSet& cs = pointSets[i];
793  pointSet set(procMesh, cs.name(), cs.size()/nProcs_);
794  forAll(curPointLabels, i)
795  {
796  if (cs.found(curPointLabels[i]))
797  {
798  set.insert(i);
799  }
800  }
801  set.write();
802  }
803  }
804 
805 
806  // Optional hexRef8 data
807  hexRef8Data
808  (
809  IOobject
810  (
811  "dummy",
812  facesInstance(),
814  procMesh,
817  false
818  ),
819  baseMeshData,
820  procCellAddressing_[proci],
821  procPointAddressing_[proci]
822  ).write();
823 
824 
825  // Statistics
826  Info<< nl << "Processor " << proci;
827 
828  if (procMesh.nCells())
829  {
830  Info<< nl << " ";
831  }
832  else
833  {
834  Info<< ": ";
835  }
836 
837  Info<< "Number of cells = " << procMesh.nCells() << nl;
838 
839  maxProcCells = max(maxProcCells, procMesh.nCells());
840 
841  label nBoundaryFaces = 0;
842  label nProcPatches = 0;
843  label nProcFaces = 0;
844 
845  forAll(procMesh.boundaryMesh(), patchi)
846  {
847  if (isA<processorPolyPatch>(procMesh.boundaryMesh()[patchi]))
848  {
849  const processorPolyPatch& ppp =
850  refCast<const processorPolyPatch>
851  (
852  procMesh.boundaryMesh()[patchi]
853  );
854 
855  Info<< " Number of faces shared with processor "
856  << ppp.neighbProcNo() << " = " << ppp.size() << endl;
857 
858  nProcPatches++;
859  nProcFaces += ppp.size();
860  }
861  else
862  {
863  nBoundaryFaces += procMesh.boundaryMesh()[patchi].size();
864  }
865  }
866 
867  if (procMesh.nCells() && (nBoundaryFaces || nProcFaces))
868  {
869  Info<< " Number of processor patches = " << nProcPatches << nl
870  << " Number of processor faces = " << nProcFaces << nl
871  << " Number of boundary faces = " << nBoundaryFaces << nl;
872  }
873 
874  totProcFaces += nProcFaces;
875  totProcPatches += nProcPatches;
876  maxProcPatches = max(maxProcPatches, nProcPatches);
877  maxProcFaces = max(maxProcFaces, nProcFaces);
878 
879  // create and write the addressing information
880  labelIOList pointProcAddressing
881  (
882  IOobject
883  (
884  "pointProcAddressing",
885  procMesh.facesInstance(),
886  procMesh.meshSubDir,
887  procMesh,
890  ),
891  procPointAddressing_[proci]
892  );
893  pointProcAddressing.write();
894 
896  (
897  IOobject
898  (
899  "faceProcAddressing",
900  procMesh.facesInstance(),
901  procMesh.meshSubDir,
902  procMesh,
905  ),
906  procFaceAddressing_[proci]
907  );
908  faceProcAddressing.write();
909 
910  labelIOList cellProcAddressing
911  (
912  IOobject
913  (
914  "cellProcAddressing",
915  procMesh.facesInstance(),
916  procMesh.meshSubDir,
917  procMesh,
920  ),
921  procCellAddressing_[proci]
922  );
923  cellProcAddressing.write();
924 
925  // Write patch map for backwards compatibility.
926  // (= identity map for original patches, -1 for processor patches)
927  label nMeshPatches = curPatchSizes.size();
928  labelList procBoundaryAddressing(identity(nMeshPatches));
929  procBoundaryAddressing.setSize(nMeshPatches+nProcPatches, -1);
930 
931  labelIOList boundaryProcAddressing
932  (
933  IOobject
934  (
935  "boundaryProcAddressing",
936  procMesh.facesInstance(),
937  procMesh.meshSubDir,
938  procMesh,
941  ),
942  procBoundaryAddressing
943  );
944  boundaryProcAddressing.write();
945  }
946 
947  scalar avgProcCells = scalar(nCells())/nProcs_;
948  scalar avgProcPatches = scalar(totProcPatches)/nProcs_;
949  scalar avgProcFaces = scalar(totProcFaces)/nProcs_;
950 
951  // In case of all faces on one processor. Just to avoid division by 0.
952  if (totProcPatches == 0)
953  {
954  avgProcPatches = 1;
955  }
956  if (totProcFaces == 0)
957  {
958  avgProcFaces = 1;
959  }
960 
961  Info<< nl
962  << "Number of processor faces = " << totProcFaces/2 << nl
963  << "Max number of cells = " << maxProcCells
964  << " (" << 100.0*(maxProcCells-avgProcCells)/avgProcCells
965  << "% above average " << avgProcCells << ")" << nl
966  << "Max number of processor patches = " << maxProcPatches
967  << " (" << 100.0*(maxProcPatches-avgProcPatches)/avgProcPatches
968  << "% above average " << avgProcPatches << ")" << nl
969  << "Max number of faces between processors = " << maxProcFaces
970  << " (" << 100.0*(maxProcFaces-avgProcFaces)/avgProcFaces
971  << "% above average " << avgProcFaces << ")" << nl
972  << endl;
973 
974  return true;
975 }
976 
977 
978 // ************************************************************************* //
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
faceProcAddressing
PtrList< labelIOList > & faceProcAddressing
Definition: checkFaceAddressingComp.H:9
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Foam::domainDecomposition::domainDecomposition
domainDecomposition(const IOobject &io, const fileName &decompDictFile="")
Construct from components.
Foam::IOobject::AUTO_WRITE
Definition: IOobject.H:129
Foam::BitOps::set
void set(List< bool > &bools, const labelRange &range)
Set the specified range 'on' in a boolList.
Definition: BitOps.C:37
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobjectI.H:70
nPatches
label nPatches
Definition: readKivaGrid.H:396
Foam::polyMesh::meshSubDir
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:321
IOobjectList.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::cellZoneMesh
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
Definition: cellZoneMeshFwd.H:44
Foam::labelIOList
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:44
Foam::Time::controlDictName
static word controlDictName
The default control dictionary name (normally "controlDict")
Definition: Time.H:226
Foam::pointZoneMesh
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
Definition: pointZoneMeshFwd.H:44
processorCyclicPolyPatch.H
nProcPatches
const label nProcPatches
Definition: convertProcessorPatches.H:171
domainDecomposition.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Map.H
Foam::faceZoneMesh
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
Definition: faceZoneMeshFwd.H:44
Foam::pointIOField
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:44
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::domainDecomposition::writeDecomposition
bool writeDecomposition(const bool decomposeSets)
Write decomposition.
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::polyPatchList
PtrList< polyPatch > polyPatchList
container classes for polyPatch
Definition: polyPatchList.H:47
faceSet.H
Foam::IOobject::READ_IF_PRESENT
Definition: IOobject.H:122
Foam::cellList
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:47
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
processorPolyPatch.H
hexRef8Data.H
fvMesh.H
fvFieldDecomposer.H
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Foam::decompositionModel::New
static const decompositionModel & New(const polyMesh &mesh, const fileName &decompDictFile="")
Read (optionally from absolute path) and register on mesh.
Definition: decompositionModel.C:116
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::nl
constexpr char nl
Definition: Ostream.H:385
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::IOstream::defaultPrecision
static unsigned int defaultPrecision()
Return the default precision.
Definition: IOstream.H:333
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
labelIOList.H
points
const pointField & points
Definition: gmvOutputHeader.H:1
dictionary.H
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
decompositionModel.H
DynamicList.H
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
cellSet.H
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::IOobject::NO_READ
Definition: IOobject.H:123
Foam::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:417
pointSet.H