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-2021 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 {
123  updateParameters(this->model());
124 }
125 
126 
127 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
128 
130 {
131  return decompositionModel::New(*this, decompDictFile_);
132 }
133 
134 
136 (
137  const dictionary& params
138 )
139 {
140  params.readIfPresent("distributed", distributed_);
141 }
142 
143 
144 bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
145 {
146  Info<< "\nConstructing processor meshes" << endl;
147 
148  // Mark point/faces/cells that are in zones.
149  // -1 : not in zone
150  // -2 : in multiple zones
151  // >= 0 : in single given zone
152  // This will give direct lookup of elements that are in a single zone
153  // and we'll only have to revert back to searching through all zones
154  // for the duplicate elements
155 
156  // Point zones
157  labelList pointToZone(points().size(), -1);
158 
159  forAll(pointZones(), zonei)
160  {
161  mark(pointZones()[zonei], zonei, pointToZone);
162  }
163 
164  // Face zones
165  labelList faceToZone(faces().size(), -1);
166 
167  forAll(faceZones(), zonei)
168  {
169  mark(faceZones()[zonei], zonei, faceToZone);
170  }
171 
172  // Cell zones
173  labelList cellToZone(nCells(), -1);
174 
175  forAll(cellZones(), zonei)
176  {
177  mark(cellZones()[zonei], zonei, cellToZone);
178  }
179 
180 
181  PtrList<const cellSet> cellSets;
182  PtrList<const faceSet> faceSets;
183  PtrList<const pointSet> pointSets;
184  if (decomposeSets)
185  {
186  // Read sets
187  IOobjectList objects(*this, facesInstance(), "polyMesh/sets");
188  {
189  IOobjectList cSets(objects.lookupClass(cellSet::typeName));
190  forAllConstIters(cSets, iter)
191  {
192  cellSets.append(new cellSet(*iter()));
193  }
194  }
195  {
196  IOobjectList fSets(objects.lookupClass(faceSet::typeName));
197  forAllConstIters(fSets, iter)
198  {
199  faceSets.append(new faceSet(*iter()));
200  }
201  }
202  {
203  IOobjectList pSets(objects.lookupClass(pointSet::typeName));
204  forAllConstIters(pSets, iter)
205  {
206  pointSets.append(new pointSet(*iter()));
207  }
208  }
209  }
210 
211 
212  // Load refinement data (if any)
213  hexRef8Data baseMeshData
214  (
215  IOobject
216  (
217  "dummy",
218  facesInstance(),
220  *this,
223  false
224  )
225  );
226 
227 
228 
229  label maxProcCells = 0;
230  label totProcFaces = 0;
231  label maxProcPatches = 0;
232  label totProcPatches = 0;
233  label maxProcFaces = 0;
234 
235 
236  // Write out the meshes
237  for (label proci = 0; proci < nProcs_; proci++)
238  {
239  // Create processor points
240  const labelList& curPointLabels = procPointAddressing_[proci];
241 
242  const pointField& meshPoints = points();
243 
244  labelList pointLookup(nPoints(), -1);
245 
246  pointField procPoints(curPointLabels.size());
247 
248  forAll(curPointLabels, pointi)
249  {
250  procPoints[pointi] = meshPoints[curPointLabels[pointi]];
251 
252  pointLookup[curPointLabels[pointi]] = pointi;
253  }
254 
255  // Create processor faces
256  const labelList& curFaceLabels = procFaceAddressing_[proci];
257 
258  const faceList& meshFaces = faces();
259 
260  labelList faceLookup(nFaces(), -1);
261 
262  faceList procFaces(curFaceLabels.size());
263 
264  forAll(curFaceLabels, facei)
265  {
266  // Mark the original face as used
267  // Remember to decrement the index by one (turning index)
268  //
269  label curF = mag(curFaceLabels[facei]) - 1;
270 
271  faceLookup[curF] = facei;
272 
273  // get the original face
274  labelList origFaceLabels;
275 
276  if (curFaceLabels[facei] >= 0)
277  {
278  // face not turned
279  origFaceLabels = meshFaces[curF];
280  }
281  else
282  {
283  origFaceLabels = meshFaces[curF].reverseFace();
284  }
285 
286  // translate face labels into local point list
287  face& procFaceLabels = procFaces[facei];
288 
289  procFaceLabels.setSize(origFaceLabels.size());
290 
291  forAll(origFaceLabels, pointi)
292  {
293  procFaceLabels[pointi] = pointLookup[origFaceLabels[pointi]];
294  }
295  }
296 
297  // Create processor cells
298  const labelList& curCellLabels = procCellAddressing_[proci];
299 
300  const cellList& meshCells = cells();
301 
302  cellList procCells(curCellLabels.size());
303 
304  forAll(curCellLabels, celli)
305  {
306  const labelList& origCellLabels = meshCells[curCellLabels[celli]];
307 
308  cell& curCell = procCells[celli];
309 
310  curCell.setSize(origCellLabels.size());
311 
312  forAll(origCellLabels, cellFacei)
313  {
314  curCell[cellFacei] = faceLookup[origCellLabels[cellFacei]];
315  }
316  }
317 
318  // Create processor mesh without a boundary
319 
320  fileName processorCasePath
321  (
322  time().caseName()/("processor" + Foam::name(proci))
323  );
324 
325  // create a database
326  Time processorDb
327  (
329  time().rootPath(),
330  processorCasePath,
331  word("system"),
332  word("constant")
333  );
334  processorDb.setTime(time());
335 
336  // create the mesh. Two situations:
337  // - points and faces come from the same time ('instance'). The mesh
338  // will get constructed in the same instance.
339  // - points come from a different time (moving mesh cases).
340  // It will read the points belonging to the faces instance and
341  // construct the procMesh with it which then gets handled as above.
342  // (so with 'old' geometry).
343  // Only at writing time will it additionally write the current
344  // points.
345 
346  autoPtr<polyMesh> procMeshPtr;
347 
348  if (facesInstancePointsPtr_)
349  {
350  // Construct mesh from facesInstance.
351  pointField facesInstancePoints
352  (
353  facesInstancePointsPtr_(),
354  curPointLabels
355  );
356 
357  procMeshPtr = autoPtr<polyMesh>::New
358  (
359  IOobject
360  (
361  this->polyMesh::name(), // region of undecomposed mesh
362  facesInstance(),
363  processorDb,
366  ),
367  std::move(facesInstancePoints),
368  std::move(procFaces),
369  std::move(procCells)
370  );
371  }
372  else
373  {
374  procMeshPtr = autoPtr<polyMesh>::New
375  (
376  IOobject
377  (
378  this->polyMesh::name(), // region of undecomposed mesh
379  facesInstance(),
380  processorDb,
383  ),
384  std::move(procPoints),
385  std::move(procFaces),
386  std::move(procCells)
387  );
388  }
389  polyMesh& procMesh = procMeshPtr();
390 
391 
392  // Create processor boundary patches
393  const labelList& curPatchSizes = procPatchSize_[proci];
394 
395  const labelList& curPatchStarts = procPatchStartIndex_[proci];
396 
397  const labelList& curNeighbourProcessors =
398  procNeighbourProcessors_[proci];
399 
400  const labelList& curProcessorPatchSizes =
401  procProcessorPatchSize_[proci];
402 
403  const labelList& curProcessorPatchStarts =
404  procProcessorPatchStartIndex_[proci];
405 
406  const labelListList& curSubPatchIDs =
407  procProcessorPatchSubPatchIDs_[proci];
408 
409  const labelListList& curSubStarts =
410  procProcessorPatchSubPatchStarts_[proci];
411 
412  const polyPatchList& meshPatches = boundaryMesh();
413 
414 
415  // Count the number of inter-proc patches
416  label nInterProcPatches = 0;
417  forAll(curSubPatchIDs, procPatchi)
418  {
419  nInterProcPatches += curSubPatchIDs[procPatchi].size();
420  }
421 
422  PtrList<polyPatch> procPatches
423  (
424  curPatchSizes.size() + nInterProcPatches
425  );
426 
427  label nPatches = 0;
428 
429  forAll(curPatchSizes, patchi)
430  {
431  // Get the face labels consistent with the field mapping
432  // (reuse the patch field mappers)
433  const polyPatch& meshPatch = meshPatches[patchi];
434 
435  fvFieldDecomposer::patchFieldDecomposer patchMapper
436  (
437  SubList<label>
438  (
439  curFaceLabels,
440  curPatchSizes[patchi],
441  curPatchStarts[patchi]
442  ),
443  meshPatch.start()
444  );
445 
446  // Map existing patches
447  procPatches.set
448  (
449  nPatches,
450  meshPatch.clone
451  (
452  procMesh.boundaryMesh(),
453  nPatches,
454  patchMapper.directAddressing(),
455  curPatchStarts[patchi]
456  )
457  );
458 
459  nPatches++;
460  }
461 
462  forAll(curProcessorPatchSizes, procPatchi)
463  {
464  const labelList& subPatchID = curSubPatchIDs[procPatchi];
465  const labelList& subStarts = curSubStarts[procPatchi];
466 
467  label curStart = curProcessorPatchStarts[procPatchi];
468 
469  forAll(subPatchID, i)
470  {
471  label size =
472  (
473  i < subPatchID.size()-1
474  ? subStarts[i+1] - subStarts[i]
475  : curProcessorPatchSizes[procPatchi] - subStarts[i]
476  );
477 
478  if (subPatchID[i] == -1)
479  {
480  // From internal faces
481  procPatches.set
482  (
483  nPatches,
484  new processorPolyPatch
485  (
486  size,
487  curStart,
488  nPatches,
489  procMesh.boundaryMesh(),
490  proci,
491  curNeighbourProcessors[procPatchi]
492  )
493  );
494  }
495  else
496  {
497  const coupledPolyPatch& pcPatch
498  = refCast<const coupledPolyPatch>
499  (
500  boundaryMesh()[subPatchID[i]]
501  );
502 
503  procPatches.set
504  (
505  nPatches,
506  new processorCyclicPolyPatch
507  (
508  size,
509  curStart,
510  nPatches,
511  procMesh.boundaryMesh(),
512  proci,
513  curNeighbourProcessors[procPatchi],
514  pcPatch.name(),
515  pcPatch.transform()
516  )
517  );
518  }
519 
520  curStart += size;
521  ++nPatches;
522  }
523  }
524 
525  // Add boundary patches
526  procMesh.addPatches(procPatches);
527 
528  // Create and add zones
529 
530  // Point zones
531  {
532  const pointZoneMesh& pz = pointZones();
533 
534  // Go through all the zoned points and find out if they
535  // belong to a zone. If so, add it to the zone as
536  // necessary
537  List<DynamicList<label>> zonePoints(pz.size());
538 
539  // Estimate size
540  forAll(zonePoints, zonei)
541  {
542  zonePoints[zonei].setCapacity(pz[zonei].size()/nProcs_);
543  }
544 
545  // Use the pointToZone map to find out the single zone (if any),
546  // use slow search only for shared points.
547  forAll(curPointLabels, pointi)
548  {
549  label curPoint = curPointLabels[pointi];
550 
551  label zonei = pointToZone[curPoint];
552 
553  if (zonei >= 0)
554  {
555  // Single zone.
556  zonePoints[zonei].append(pointi);
557  }
558  else if (zonei == -2)
559  {
560  // Multiple zones. Lookup.
561  forAll(pz, zonei)
562  {
563  label index = pz[zonei].whichPoint(curPoint);
564 
565  if (index != -1)
566  {
567  zonePoints[zonei].append(pointi);
568  }
569  }
570  }
571  }
572 
573  procMesh.pointZones().clearAddressing();
574  procMesh.pointZones().setSize(zonePoints.size());
575  forAll(zonePoints, zonei)
576  {
577  procMesh.pointZones().set
578  (
579  zonei,
580  pz[zonei].clone
581  (
582  procMesh.pointZones(),
583  zonei,
584  zonePoints[zonei].shrink()
585  )
586  );
587  }
588 
589  if (pz.size())
590  {
591  // Force writing on all processors
592  procMesh.pointZones().writeOpt(IOobject::AUTO_WRITE);
593  }
594  }
595 
596  // Face zones
597  {
598  const faceZoneMesh& fz = faceZones();
599 
600  // Go through all the zoned face and find out if they
601  // belong to a zone. If so, add it to the zone as
602  // necessary
603  List<DynamicList<label>> zoneFaces(fz.size());
604  List<DynamicList<bool>> zoneFaceFlips(fz.size());
605 
606  // Estimate size
607  forAll(zoneFaces, zonei)
608  {
609  label procSize = fz[zonei].size() / nProcs_;
610 
611  zoneFaces[zonei].setCapacity(procSize);
612  zoneFaceFlips[zonei].setCapacity(procSize);
613  }
614 
615  // Go through all the zoned faces and find out if they
616  // belong to a zone. If so, add it to the zone as
617  // necessary
618  forAll(curFaceLabels, facei)
619  {
620  // Remember to decrement the index by one (turning index)
621  //
622  label curF = mag(curFaceLabels[facei]) - 1;
623 
624  label zonei = faceToZone[curF];
625 
626  if (zonei >= 0)
627  {
628  // Single zone. Add the face
629  zoneFaces[zonei].append(facei);
630 
631  label index = fz[zonei].whichFace(curF);
632 
633  bool flip = fz[zonei].flipMap()[index];
634 
635  if (curFaceLabels[facei] < 0)
636  {
637  flip = !flip;
638  }
639 
640  zoneFaceFlips[zonei].append(flip);
641  }
642  else if (zonei == -2)
643  {
644  // Multiple zones. Lookup.
645  forAll(fz, zonei)
646  {
647  label index = fz[zonei].whichFace(curF);
648 
649  if (index != -1)
650  {
651  zoneFaces[zonei].append(facei);
652 
653  bool flip = fz[zonei].flipMap()[index];
654 
655  if (curFaceLabels[facei] < 0)
656  {
657  flip = !flip;
658  }
659 
660  zoneFaceFlips[zonei].append(flip);
661  }
662  }
663  }
664  }
665 
666  procMesh.faceZones().clearAddressing();
667  procMesh.faceZones().setSize(zoneFaces.size());
668  forAll(zoneFaces, zonei)
669  {
670  procMesh.faceZones().set
671  (
672  zonei,
673  fz[zonei].clone
674  (
675  zoneFaces[zonei].shrink(), // addressing
676  zoneFaceFlips[zonei].shrink(), // flipmap
677  zonei,
678  procMesh.faceZones()
679  )
680  );
681  }
682 
683  if (fz.size())
684  {
685  // Force writing on all processors
686  procMesh.faceZones().writeOpt(IOobject::AUTO_WRITE);
687  }
688  }
689 
690  // Cell zones
691  {
692  const cellZoneMesh& cz = cellZones();
693 
694  // Go through all the zoned cells and find out if they
695  // belong to a zone. If so, add it to the zone as
696  // necessary
697  List<DynamicList<label>> zoneCells(cz.size());
698 
699  // Estimate size
700  forAll(zoneCells, zonei)
701  {
702  zoneCells[zonei].setCapacity(cz[zonei].size()/nProcs_);
703  }
704 
705  forAll(curCellLabels, celli)
706  {
707  label curCelli = curCellLabels[celli];
708 
709  label zonei = cellToZone[curCelli];
710 
711  if (zonei >= 0)
712  {
713  // Single zone.
714  zoneCells[zonei].append(celli);
715  }
716  else if (zonei == -2)
717  {
718  // Multiple zones. Lookup.
719  forAll(cz, zonei)
720  {
721  label index = cz[zonei].whichCell(curCelli);
722 
723  if (index != -1)
724  {
725  zoneCells[zonei].append(celli);
726  }
727  }
728  }
729  }
730 
731  procMesh.cellZones().clearAddressing();
732  procMesh.cellZones().setSize(zoneCells.size());
733  forAll(zoneCells, zonei)
734  {
735  procMesh.cellZones().set
736  (
737  zonei,
738  cz[zonei].clone
739  (
740  zoneCells[zonei].shrink(),
741  zonei,
742  procMesh.cellZones()
743  )
744  );
745  }
746 
747  if (cz.size())
748  {
749  // Force writing on all processors
750  procMesh.cellZones().writeOpt(IOobject::AUTO_WRITE);
751  }
752  }
753 
754  // Set the precision of the points data to be min 10
756 
757  procMesh.write();
758 
759  // Write points if pointsInstance differing from facesInstance
760  if (facesInstancePointsPtr_)
761  {
762  pointIOField pointsInstancePoints
763  (
764  IOobject
765  (
766  "points",
767  pointsInstance(),
769  procMesh,
772  false
773  ),
774  std::move(procPoints)
775  );
776  pointsInstancePoints.write();
777  }
778 
779 
780  // Decompose any sets
781  if (decomposeSets)
782  {
783  forAll(cellSets, i)
784  {
785  const cellSet& cs = cellSets[i];
786  cellSet set(procMesh, cs.name(), cs.size()/nProcs_);
787  forAll(curCellLabels, i)
788  {
789  if (cs.found(curCellLabels[i]))
790  {
791  set.insert(i);
792  }
793  }
794  set.write();
795  }
796  forAll(faceSets, i)
797  {
798  const faceSet& cs = faceSets[i];
799  faceSet set(procMesh, cs.name(), cs.size()/nProcs_);
800  forAll(curFaceLabels, i)
801  {
802  if (cs.found(mag(curFaceLabels[i])-1))
803  {
804  set.insert(i);
805  }
806  }
807  set.write();
808  }
809  forAll(pointSets, i)
810  {
811  const pointSet& cs = pointSets[i];
812  pointSet set(procMesh, cs.name(), cs.size()/nProcs_);
813  forAll(curPointLabels, i)
814  {
815  if (cs.found(curPointLabels[i]))
816  {
817  set.insert(i);
818  }
819  }
820  set.write();
821  }
822  }
823 
824 
825  // Optional hexRef8 data
826  hexRef8Data
827  (
828  IOobject
829  (
830  "dummy",
831  facesInstance(),
833  procMesh,
836  false
837  ),
838  baseMeshData,
839  procCellAddressing_[proci],
840  procPointAddressing_[proci]
841  ).write();
842 
843 
844  // Statistics
845  Info<< nl << "Processor " << proci;
846 
847  if (procMesh.nCells())
848  {
849  Info<< nl << " ";
850  }
851  else
852  {
853  Info<< ": ";
854  }
855 
856  Info<< "Number of cells = " << procMesh.nCells() << nl;
857 
858  maxProcCells = max(maxProcCells, procMesh.nCells());
859 
860  label nBoundaryFaces = 0;
861  label nProcPatches = 0;
862  label nProcFaces = 0;
863 
864  forAll(procMesh.boundaryMesh(), patchi)
865  {
866  if (isA<processorPolyPatch>(procMesh.boundaryMesh()[patchi]))
867  {
868  const processorPolyPatch& ppp =
869  refCast<const processorPolyPatch>
870  (
871  procMesh.boundaryMesh()[patchi]
872  );
873 
874  Info<< " Number of faces shared with processor "
875  << ppp.neighbProcNo() << " = " << ppp.size() << endl;
876 
877  nProcPatches++;
878  nProcFaces += ppp.size();
879  }
880  else
881  {
882  nBoundaryFaces += procMesh.boundaryMesh()[patchi].size();
883  }
884  }
885 
886  if (procMesh.nCells() && (nBoundaryFaces || nProcFaces))
887  {
888  Info<< " Number of processor patches = " << nProcPatches << nl
889  << " Number of processor faces = " << nProcFaces << nl
890  << " Number of boundary faces = " << nBoundaryFaces << nl;
891  }
892 
893  totProcFaces += nProcFaces;
894  totProcPatches += nProcPatches;
895  maxProcPatches = max(maxProcPatches, nProcPatches);
896  maxProcFaces = max(maxProcFaces, nProcFaces);
897 
898  // create and write the addressing information
899  labelIOList pointProcAddressing
900  (
901  IOobject
902  (
903  "pointProcAddressing",
904  procMesh.facesInstance(),
905  procMesh.meshSubDir,
906  procMesh,
909  ),
910  procPointAddressing_[proci]
911  );
912  pointProcAddressing.write();
913 
915  (
916  IOobject
917  (
918  "faceProcAddressing",
919  procMesh.facesInstance(),
920  procMesh.meshSubDir,
921  procMesh,
924  ),
925  procFaceAddressing_[proci]
926  );
927  faceProcAddressing.write();
928 
929  labelIOList cellProcAddressing
930  (
931  IOobject
932  (
933  "cellProcAddressing",
934  procMesh.facesInstance(),
935  procMesh.meshSubDir,
936  procMesh,
939  ),
940  procCellAddressing_[proci]
941  );
942  cellProcAddressing.write();
943 
944  // Write patch map for backwards compatibility.
945  // (= identity map for original patches, -1 for processor patches)
946  label nMeshPatches = curPatchSizes.size();
947  labelList procBoundaryAddressing(identity(nMeshPatches));
948  procBoundaryAddressing.setSize(nMeshPatches+nProcPatches, -1);
949 
950  labelIOList boundaryProcAddressing
951  (
952  IOobject
953  (
954  "boundaryProcAddressing",
955  procMesh.facesInstance(),
956  procMesh.meshSubDir,
957  procMesh,
960  ),
961  procBoundaryAddressing
962  );
963  boundaryProcAddressing.write();
964  }
965 
966  scalar avgProcCells = scalar(nCells())/nProcs_;
967  scalar avgProcPatches = scalar(totProcPatches)/nProcs_;
968  scalar avgProcFaces = scalar(totProcFaces)/nProcs_;
969 
970  // In case of all faces on one processor. Just to avoid division by 0.
971  if (totProcPatches == 0)
972  {
973  avgProcPatches = 1;
974  }
975  if (totProcFaces == 0)
976  {
977  avgProcFaces = 1;
978  }
979 
980  Info<< nl
981  << "Number of processor faces = " << totProcFaces/2 << nl
982  << "Max number of cells = " << maxProcCells
983  << " (" << 100.0*(maxProcCells-avgProcCells)/avgProcCells
984  << "% above average " << avgProcCells << ")" << nl
985  << "Max number of processor patches = " << maxProcPatches
986  << " (" << 100.0*(maxProcPatches-avgProcPatches)/avgProcPatches
987  << "% above average " << avgProcPatches << ")" << nl
988  << "Max number of faces between processors = " << maxProcFaces
989  << " (" << 100.0*(maxProcFaces-avgProcFaces)/avgProcFaces
990  << "% above average " << avgProcFaces << ")" << nl
991  << endl;
992 
993  return true;
994 }
995 
996 
997 // ************************************************************************* //
Foam::IOobject::NO_WRITE
@ NO_WRITE
Definition: IOobject.H:191
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:63
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
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="")
Foam::IOobject::AUTO_WRITE
@ AUTO_WRITE
Definition: IOobject.H:190
Foam::BitOps::set
void set(List< bool > &bools, const labelRange &range)
Definition: BitOps.C:30
Foam::domainDecomposition::model
const decompositionModel & model() const
Foam::polyMesh::meshSubDir
static word meshSubDir
Definition: polyMesh.H:317
IOobjectList.H
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
Foam::cellZoneMesh
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
Definition: cellZoneMeshFwd.H:38
Foam::labelIOList
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:38
Foam::Time::controlDictName
static word controlDictName
Definition: Time.H:222
Foam::pointZoneMesh
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
Definition: pointZoneMeshFwd.H:38
processorCyclicPolyPatch.H
Foam::decompositionModel
MeshObject wrapper of decompositionMethod.
Definition: decompositionModel.H:53
nProcPatches
const label nProcPatches
Definition: convertProcessorPatches.H:165
domainDecomposition.H
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
Foam::decompositionModel::New
static const decompositionModel & New(const polyMesh &mesh, const fileName &decompDictFile="", const dictionary *fallback=nullptr)
Definition: decompositionModel.C:76
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Map.H
Foam::faceZoneMesh
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
Definition: faceZoneMeshFwd.H:38
nPatches
const label nPatches
Definition: printMeshSummary.H:24
Foam::pointIOField
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:38
Foam::Info
messageStream Info
Foam::domainDecomposition::writeDecomposition
bool writeDecomposition(const bool decomposeSets)
Foam::polyPatchList
PtrList< polyPatch > polyPatchList
container classes for polyPatch
Definition: polyPatchList.H:41
Foam::List::setSize
void setSize(const label n)
Definition: List.H:218
faceSet.H
Foam::IOobject::READ_IF_PRESENT
@ READ_IF_PRESENT
Definition: IOobject.H:183
Foam::cellList
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:41
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Definition: hashSets.C:40
processorPolyPatch.H
hexRef8Data.H
fvMesh.H
Foam::domainDecomposition::updateParameters
void updateParameters(const dictionary &params)
fvFieldDecomposer.H
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Definition: DimensionedFieldReuseFunctions.H:100
Foam::IOobject::name
const word & name() const noexcept
Definition: IOobjectI.H:58
Foam::IOstream::defaultPrecision
static unsigned int defaultPrecision() noexcept
Definition: IOstream.H:338
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:51
Foam::nl
constexpr char nl
Definition: Ostream.H:424
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:41
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)
Definition: labelList.C:31
Foam::name
word name(const expressions::valueTypeCode typeCode)
Definition: exprTraits.C:52
decompositionModel.H
DynamicList.H
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
cellSet.H
Foam::IOobject::NO_READ
@ NO_READ
Definition: IOobject.H:184
pointSet.H