decompositionMethod.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) 2015-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 "decompositionMethod.H"
30 #include "globalIndex.H"
31 #include "syncTools.H"
32 #include "Tuple2.H"
33 #include "faceSet.H"
34 #include "regionSplit.H"
35 #include "localPointRegion.H"
36 #include "minData.H"
37 #include "BitOps.H"
38 #include "FaceCellWave.H"
39 
40 // Compatibility (MAY-2014)
45 
46 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
47 
48 namespace Foam
49 {
50  defineTypeNameAndDebug(decompositionMethod, 0);
51  defineRunTimeSelectionTable(decompositionMethod, dictionary);
52  defineRunTimeSelectionTable(decompositionMethod, dictionaryRegion);
53 
54  // Fallback name when searching for optional coefficients directories
55  static const word defaultName("coeffs");
56 
57 } // End namespace Foam
58 
59 
60 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
61 
62 Foam::label Foam::decompositionMethod::nDomains(const dictionary& decompDict)
63 {
64  return decompDict.get<label>("numberOfSubdomains");
65 }
66 
67 
69 (
70  const dictionary& decompDict,
71  const word& regionName
72 )
73 {
74  const label nDomainsGlobal = nDomains(decompDict);
75 
76  const dictionary& regionDict(optionalRegionDict(decompDict, regionName));
77 
78  label nDomainsRegion;
79  if (regionDict.readIfPresent("numberOfSubdomains", nDomainsRegion))
80  {
81  if (nDomainsRegion >= 1 && nDomainsRegion <= nDomainsGlobal)
82  {
83  return nDomainsRegion;
84  }
85 
87  << "ignoring out of range numberOfSubdomains "
88  << nDomainsRegion << " for region " << regionName
89  << nl << nl
90  << endl;
91  }
92 
93  return nDomainsGlobal;
94 }
95 
96 
98 (
99  const dictionary& decompDict,
100  const word& regionName
101 )
102 {
103  auto finder = decompDict.csearch("regions");
104 
105  if (!regionName.empty() && finder.isDict())
106  {
107  finder = finder.dict().csearch(regionName);
108 
109  if (finder.isDict())
110  {
111  return finder.dict();
112  }
113  }
114 
115  return dictionary::null;
116 }
117 
118 
119 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
120 
121 bool Foam::decompositionMethod::constraintCompat(const word& modelType) const
122 {
123  bool usable = decompDict_.found(modelType);
124  if (!usable)
125  {
126  return false;
127  }
128 
129  for (const auto& item : constraints_)
130  {
131  if (modelType == item.type())
132  {
133  usable = false;
134  break;
135  }
136  }
137 
138  if (usable)
139  {
140  Warning
141  << nl << " Using '" << modelType
142  << "' constraint specification." << nl;
143  }
144  else
145  {
146  Warning
147  << nl << " Ignoring '" << modelType
148  << "' constraint specification - was already specified." << nl;
149  }
150 
151  // The syntax changed MAY-2014
152  error::warnAboutAge("constraint keyword", 1406);
153 
154  return usable;
155 }
156 
157 
158 void Foam::decompositionMethod::readConstraints()
159 {
160  constraints_.clear();
161 
162  const dictionary* dictptr = decompDict_.findDict("constraints");
163 
164  if (dictptr)
165  {
166  for (const entry& dEntry : *dictptr)
167  {
168  if (!dEntry.isDict()) // safety
169  {
170  // Ignore or warn
171  continue;
172  }
173 
174  const dictionary& dict = dEntry.dict();
175 
176  if (dict.getOrDefault("enabled", true))
177  {
178  constraints_.append(decompositionConstraint::New(dict));
179  }
180  }
181  }
182 
183  // Backwards compatibility (MAY-2014)
184  if (constraintCompat("preserveBaffles"))
185  {
186  constraints_.append
187  (
188  new decompositionConstraints::preserveBaffles()
189  );
190  }
191 
192  if (constraintCompat("preservePatches"))
193  {
194  constraints_.append
195  (
196  new decompositionConstraints::preservePatches
197  (
198  decompDict_.get<wordRes>("preservePatches")
199  )
200  );
201  }
202 
203  if (constraintCompat("preserveFaceZones"))
204  {
205  constraints_.append
206  (
207  new decompositionConstraints::preserveFaceZones
208  (
209  decompDict_.get<wordRes>("preserveFaceZones")
210  )
211  );
212  }
213 
214  if (constraintCompat("singleProcessorFaceSets"))
215  {
216  constraints_.append
217  (
218  new decompositionConstraints::singleProcessorFaceSets
219  (
220  decompDict_.lookup("singleProcessorFaceSets")
221  )
222  );
223  }
224 }
225 
226 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
227 
229 (
230  const dictionary& dict,
231  const word& coeffsName,
232  int select
233 )
234 {
236 
237  if
238  (
239  (fnd = dict.csearch(coeffsName)).isDict()
240  ||
241  (
242  !(select & selectionType::EXACT)
243  && (fnd = dict.csearch(defaultName)).isDict()
244  )
245  )
246  {
247  return fnd.dict();
248  }
249 
250  // Not found
251  if (select & selectionType::MANDATORY)
252  {
254  << "'" << coeffsName << "' dictionary not found in dictionary "
255  << dict.name() << endl
256  << abort(FatalIOError);
257  }
258 
259  if (select & selectionType::NULL_DICT)
260  {
261  return dictionary::null;
262  }
263 
264  return dict;
265 }
266 
267 
269 (
270  const word& coeffsName,
271  int select
272 ) const
273 {
275 
276  if
277  (
278  !decompRegionDict_.empty()
279  &&
280  (
281  (fnd = decompRegionDict_.csearch(coeffsName)).isDict()
282  ||
283  (
284  !(select & selectionType::EXACT)
285  && (fnd = decompRegionDict_.csearch(defaultName)).isDict()
286  )
287  )
288  )
289  {
290  return fnd.dict();
291  }
292 
293  if
294  (
295  (fnd = decompDict_.csearch(coeffsName)).isDict()
296  ||
297  (
298  !(select & selectionType::EXACT)
299  && (fnd = decompDict_.csearch(defaultName)).isDict()
300  )
301  )
302  {
303  return fnd.dict();
304  }
305 
306  // Not found
307  if (select & selectionType::MANDATORY)
308  {
310  << "'" << coeffsName << "' dictionary not found in dictionary "
311  << decompDict_.name() << endl
312  << abort(FatalIOError);
313  }
314 
315  if (select & selectionType::NULL_DICT)
316  {
317  return dictionary::null;
318  }
319 
320  return decompDict_;
321 }
322 
323 
324 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
325 
326 Foam::decompositionMethod::decompositionMethod
327 (
328  const dictionary& decompDict
329 )
330 :
331  decompDict_(decompDict),
332  decompRegionDict_(dictionary::null),
333  nDomains_(nDomains(decompDict))
334 {
335  readConstraints();
336 }
337 
338 
339 Foam::decompositionMethod::decompositionMethod
340 (
341  const dictionary& decompDict,
342  const word& regionName
343 )
344 :
345  decompDict_(decompDict),
346  decompRegionDict_
347  (
348  optionalRegionDict(decompDict_, regionName)
349  ),
350  nDomains_(nDomains(decompDict, regionName))
351 {
352  readConstraints();
353 }
354 
355 
356 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
357 
359 (
360  const dictionary& decompDict
361 )
362 {
363  const word methodType(decompDict.get<word>("method"));
364 
365  auto cstrIter = dictionaryConstructorTablePtr_->cfind(methodType);
366 
367  if (!cstrIter.found())
368  {
370  (
371  decompDict,
372  "decompositionMethod",
373  methodType,
374  *dictionaryConstructorTablePtr_
375  ) << exit(FatalIOError);
376  }
377 
378  // verbose
379  {
380  Info<< "Selecting decompositionMethod " << methodType
381  << " [" << (nDomains(decompDict)) << "]" << endl;
382  }
383 
384  return autoPtr<decompositionMethod>(cstrIter()(decompDict));
385 }
386 
387 
389 (
390  const dictionary& decompDict,
391  const word& regionName
392 )
393 {
394  const dictionary& regionDict(optionalRegionDict(decompDict, regionName));
395 
396  if (regionDict.empty())
397  {
398  // No region-specific information - just forward to normal routine
399  return decompositionMethod::New(decompDict);
400  }
401 
402  word methodType(decompDict.get<word>("method"));
403  regionDict.readIfPresent("method", methodType);
404 
405  auto cstrIter = dictionaryRegionConstructorTablePtr_->cfind(methodType);
406 
407  if (!cstrIter.found())
408  {
410  << nl
411  << "Unknown region decompositionMethod "
412  << methodType << nl << nl
413  << "Valid decompositionMethods : " << endl
414  << dictionaryRegionConstructorTablePtr_->sortedToc() << nl
415  << "Reverting to non-region version" << nl
416  << endl;
417 
418  return decompositionMethod::New(decompDict);
419  }
420 
421  // verbose
422  {
423  Info<< "Selecting decompositionMethod " << methodType
424  << " [" << (nDomains(decompDict, regionName)) << "] (region "
425  << regionName << ")" << endl;
426  }
427 
428  return autoPtr<decompositionMethod>(cstrIter()(decompDict, regionName));
429 }
430 
431 
433 (
434  const polyMesh& mesh,
435  const pointField& points
436 ) const
437 {
438  scalarField weights(points.size(), scalar(1));
439 
440  return decompose(mesh, points, weights);
441 }
442 
443 
445 (
446  const polyMesh& mesh,
447  const labelList& fineToCoarse,
448  const pointField& coarsePoints,
449  const scalarField& coarseWeights
450 ) const
451 {
452  CompactListList<label> coarseCellCells;
453  calcCellCells
454  (
455  mesh,
456  fineToCoarse,
457  coarsePoints.size(),
458  true, // use global cell labels
459  coarseCellCells
460  );
461 
462  // Decompose based on agglomerated points
463  labelList coarseDistribution
464  (
465  decompose
466  (
467  coarseCellCells(),
468  coarsePoints,
469  coarseWeights
470  )
471  );
472 
473  // Rework back into decomposition for original mesh_
474  labelList fineDistribution(fineToCoarse.size());
475 
476  forAll(fineDistribution, i)
477  {
478  fineDistribution[i] = coarseDistribution[fineToCoarse[i]];
479  }
480 
481  return fineDistribution;
482 }
483 
484 
486 (
487  const polyMesh& mesh,
488  const labelList& fineToCoarse,
489  const pointField& coarsePoints
490 ) const
491 {
492  scalarField weights(coarsePoints.size(), scalar(1));
493 
494  return decompose
495  (
496  mesh,
497  fineToCoarse,
498  coarsePoints,
499  weights
500  );
501 }
502 
503 
505 (
506  const labelListList& globalCellCells,
507  const pointField& cc
508 ) const
509 {
510  scalarField weights(cc.size(), scalar(1));
511 
512  return decompose(globalCellCells, cc, weights);
513 }
514 
515 
517 (
518  const polyMesh& mesh,
519  const labelList& agglom,
520  const label nLocalCoarse,
521  const bool parallel,
522  CompactListList<label>& cellCells
523 )
524 {
525  const labelList& faceOwner = mesh.faceOwner();
526  const labelList& faceNeighbour = mesh.faceNeighbour();
528 
529 
530  // Create global cell numbers
531  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
532 
533  globalIndex globalAgglom
534  (
535  nLocalCoarse,
538  parallel
539  );
540 
541 
542  // Get agglomerate owner on other side of coupled faces
543  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
544 
545  labelList globalNeighbour(mesh.nBoundaryFaces());
546 
547  for (const polyPatch& pp : patches)
548  {
549  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
550  {
551  label facei = pp.start();
552  label bFacei = pp.start() - mesh.nInternalFaces();
553 
554  forAll(pp, i)
555  {
556  globalNeighbour[bFacei] = globalAgglom.toGlobal
557  (
558  agglom[faceOwner[facei]]
559  );
560 
561  ++facei;
562  ++bFacei;
563  }
564  }
565  }
566 
567  // Get the cell on the other side of coupled patches
568  syncTools::swapBoundaryFaceList(mesh, globalNeighbour);
569 
570 
571  // Count number of faces (internal + coupled)
572  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
573 
574  // Number of faces per coarse cell
575  labelList nFacesPerCell(nLocalCoarse, Zero);
576 
577  for (label facei = 0; facei < mesh.nInternalFaces(); ++facei)
578  {
579  const label own = agglom[faceOwner[facei]];
580  const label nei = agglom[faceNeighbour[facei]];
581 
582  nFacesPerCell[own]++;
583  nFacesPerCell[nei]++;
584  }
585 
586  for (const polyPatch& pp : patches)
587  {
588  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
589  {
590  label facei = pp.start();
591  label bFacei = pp.start()-mesh.nInternalFaces();
592 
593  forAll(pp, i)
594  {
595  const label own = agglom[faceOwner[facei]];
596  const label globalNei = globalNeighbour[bFacei];
597 
598  if
599  (
600  !globalAgglom.isLocal(globalNei)
601  || globalAgglom.toLocal(globalNei) != own
602  )
603  {
604  nFacesPerCell[own]++;
605  }
606 
607  ++facei;
608  ++bFacei;
609  }
610  }
611  }
612 
613 
614  // Fill in offset and data
615  // ~~~~~~~~~~~~~~~~~~~~~~~
616 
617  cellCells.setSize(nFacesPerCell);
618 
619  nFacesPerCell = 0;
620 
621  labelList& m = cellCells.m();
622  const labelList& offsets = cellCells.offsets();
623 
624  // For internal faces is just offsetted owner and neighbour
625  for (label facei = 0; facei < mesh.nInternalFaces(); ++facei)
626  {
627  const label own = agglom[faceOwner[facei]];
628  const label nei = agglom[faceNeighbour[facei]];
629 
630  m[offsets[own] + nFacesPerCell[own]++] = globalAgglom.toGlobal(nei);
631  m[offsets[nei] + nFacesPerCell[nei]++] = globalAgglom.toGlobal(own);
632  }
633 
634  // For boundary faces is offsetted coupled neighbour
635  for (const polyPatch& pp : patches)
636  {
637  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
638  {
639  label facei = pp.start();
640  label bFacei = pp.start()-mesh.nInternalFaces();
641 
642  forAll(pp, i)
643  {
644  const label own = agglom[faceOwner[facei]];
645  const label globalNei = globalNeighbour[bFacei];
646 
647  if
648  (
649  !globalAgglom.isLocal(globalNei)
650  || globalAgglom.toLocal(globalNei) != own
651  )
652  {
653  m[offsets[own] + nFacesPerCell[own]++] = globalNei;
654  }
655 
656  ++facei;
657  ++bFacei;
658  }
659  }
660  }
661 
662 
663  // Check for duplicates connections between cells
664  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
665  // Done as postprocessing step since we now have cellCells.
666 
667  if (cellCells.size() == 0)
668  {
669  return;
670  }
671 
672  label newIndex = 0;
673  labelHashSet nbrCells;
674 
675  label startIndex = cellCells.offsets()[0];
676 
677  forAll(cellCells, celli)
678  {
679  nbrCells.clear();
680  nbrCells.insert(globalAgglom.toGlobal(celli));
681 
682  const label endIndex = cellCells.offsets()[celli+1];
683 
684  for (label i = startIndex; i < endIndex; ++i)
685  {
686  if (nbrCells.insert(cellCells.m()[i]))
687  {
688  cellCells.m()[newIndex++] = cellCells.m()[i];
689  }
690  }
691  startIndex = endIndex;
692  cellCells.offsets()[celli+1] = newIndex;
693  }
694 
695  cellCells.m().setSize(newIndex);
696 
697  //forAll(cellCells, celli)
698  //{
699  // Pout<< "Original: Coarse cell " << celli << endl;
700  // forAll(mesh.cellCells()[celli], i)
701  // {
702  // Pout<< " nbr:" << mesh.cellCells()[celli][i] << endl;
703  // }
704  // Pout<< "Compacted: Coarse cell " << celli << endl;
705  // const labelUList cCells = cellCells[celli];
706  // forAll(cCells, i)
707  // {
708  // Pout<< " nbr:" << cCells[i] << endl;
709  // }
710  //}
711 }
712 
713 
715 (
716  const polyMesh& mesh,
717  const labelList& agglom,
718  const label nLocalCoarse,
719  const bool parallel,
720  CompactListList<label>& cellCells,
721  CompactListList<scalar>& cellCellWeights
722 )
723 {
724  const labelList& faceOwner = mesh.faceOwner();
725  const labelList& faceNeighbour = mesh.faceNeighbour();
727 
728 
729  // Create global cell numbers
730  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
731 
732  globalIndex globalAgglom
733  (
734  nLocalCoarse,
737  parallel
738  );
739 
740 
741  // Get agglomerate owner on other side of coupled faces
742  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
743 
744  labelList globalNeighbour(mesh.nBoundaryFaces());
745 
746  for (const polyPatch& pp : patches)
747  {
748  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
749  {
750  label facei = pp.start();
751  label bFacei = pp.start() - mesh.nInternalFaces();
752 
753  forAll(pp, i)
754  {
755  globalNeighbour[bFacei] = globalAgglom.toGlobal
756  (
757  agglom[faceOwner[facei]]
758  );
759 
760  ++facei;
761  ++bFacei;
762  }
763  }
764  }
765 
766  // Get the cell on the other side of coupled patches
767  syncTools::swapBoundaryFaceList(mesh, globalNeighbour);
768 
769 
770  // Count number of faces (internal + coupled)
771  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
772 
773  // Number of faces per coarse cell
774  labelList nFacesPerCell(nLocalCoarse, Zero);
775 
776  for (label facei = 0; facei < mesh.nInternalFaces(); ++facei)
777  {
778  const label own = agglom[faceOwner[facei]];
779  const label nei = agglom[faceNeighbour[facei]];
780 
781  nFacesPerCell[own]++;
782  nFacesPerCell[nei]++;
783  }
784 
785  for (const polyPatch& pp : patches)
786  {
787  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
788  {
789  label facei = pp.start();
790  label bFacei = pp.start() - mesh.nInternalFaces();
791 
792  forAll(pp, i)
793  {
794  const label own = agglom[faceOwner[facei]];
795  const label globalNei = globalNeighbour[bFacei];
796 
797  if
798  (
799  !globalAgglom.isLocal(globalNei)
800  || globalAgglom.toLocal(globalNei) != own
801  )
802  {
803  nFacesPerCell[own]++;
804  }
805 
806  ++facei;
807  ++bFacei;
808  }
809  }
810  }
811 
812 
813  // Fill in offset and data
814  // ~~~~~~~~~~~~~~~~~~~~~~~
815 
816  cellCells.setSize(nFacesPerCell);
817  cellCellWeights.setSize(nFacesPerCell);
818 
819  nFacesPerCell = 0;
820 
821  labelList& m = cellCells.m();
822  scalarList& w = cellCellWeights.m();
823  const labelList& offsets = cellCells.offsets();
824 
825  // For internal faces is just offsetted owner and neighbour
826  for (label facei = 0; facei < mesh.nInternalFaces(); ++facei)
827  {
828  const label own = agglom[faceOwner[facei]];
829  const label nei = agglom[faceNeighbour[facei]];
830 
831  const label ownIndex = offsets[own] + nFacesPerCell[own]++;
832  const label neiIndex = offsets[nei] + nFacesPerCell[nei]++;
833 
834  m[ownIndex] = globalAgglom.toGlobal(nei);
835  w[ownIndex] = mag(mesh.faceAreas()[facei]);
836  m[neiIndex] = globalAgglom.toGlobal(own);
837  w[ownIndex] = mag(mesh.faceAreas()[facei]);
838  }
839 
840  // For boundary faces is offsetted coupled neighbour
841  for (const polyPatch& pp : patches)
842  {
843  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
844  {
845  label facei = pp.start();
846  label bFacei = pp.start()-mesh.nInternalFaces();
847 
848  forAll(pp, i)
849  {
850  const label own = agglom[faceOwner[facei]];
851  const label globalNei = globalNeighbour[bFacei];
852 
853  if
854  (
855  !globalAgglom.isLocal(globalNei)
856  || globalAgglom.toLocal(globalNei) != own
857  )
858  {
859  const label ownIndex = offsets[own] + nFacesPerCell[own]++;
860  m[ownIndex] = globalNei;
861  w[ownIndex] = mag(mesh.faceAreas()[facei]);
862  }
863 
864  ++facei;
865  ++bFacei;
866  }
867  }
868  }
869 
870 
871  // Check for duplicates connections between cells
872  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
873  // Done as postprocessing step since we now have cellCells.
874 
875  if (cellCells.size() == 0)
876  {
877  return;
878  }
879 
880  label newIndex = 0;
881  labelHashSet nbrCells;
882 
883  label startIndex = cellCells.offsets()[0];
884 
885  forAll(cellCells, celli)
886  {
887  nbrCells.clear();
888  nbrCells.insert(globalAgglom.toGlobal(celli));
889 
890  const label endIndex = cellCells.offsets()[celli+1];
891 
892  for (label i = startIndex; i < endIndex; ++i)
893  {
894  if (nbrCells.insert(cellCells.m()[i]))
895  {
896  cellCells.m()[newIndex] = cellCells.m()[i];
897  cellCellWeights.m()[newIndex] = cellCellWeights.m()[i];
898  newIndex++;
899  }
900  }
901  startIndex = endIndex;
902  cellCells.offsets()[celli+1] = newIndex;
903  cellCellWeights.offsets()[celli+1] = newIndex;
904  }
905 
906  cellCells.m().setSize(newIndex);
907  cellCellWeights.m().setSize(newIndex);
908 }
909 
910 
911 // NOTE:
912 // - alternative calcCellCells that handled explicitConnections was
913 // deactivated (2014 or earlier) and finally removed APR-2018.
914 
916 (
917  const polyMesh& mesh,
918  const scalarField& cellWeights,
919 
920  //- Whether owner and neighbour should be on same processor
921  // (takes priority over explicitConnections)
922  const boolList& blockedFace,
923 
924  //- Whether whole sets of faces (and point neighbours) need to be kept
925  // on single processor
926  const PtrList<labelList>& specifiedProcessorFaces,
927  const labelList& specifiedProcessor,
928 
929  //- Additional connections between boundary faces
930  const List<labelPair>& explicitConnections
931 ) const
932 {
933  // Any weights specified?
934  const bool hasWeights = returnReduce(!cellWeights.empty(), orOp<bool>());
935 
936  if (hasWeights && cellWeights.size() != mesh.nCells())
937  {
939  << "Number of weights " << cellWeights.size()
940  << " differs from number of cells " << mesh.nCells()
941  << exit(FatalError);
942  }
943 
944  // Any faces not blocked?
945  const bool hasUnblocked =
947  (
948  (!blockedFace.empty() && !BitOps::all(blockedFace)),
949  orOp<bool>()
950  );
951 
952 
953  // Any non-mesh connections?
954  const label nConnections = returnReduce
955  (
956  explicitConnections.size(),
957  sumOp<label>()
958  );
959 
960 
961  // Any processor sets?
962  label nProcSets = 0;
963  for (const labelList& procset : specifiedProcessorFaces)
964  {
965  nProcSets += procset.size();
966  }
967  reduce(nProcSets, sumOp<label>());
968 
969 
970  // Either do decomposition on cell centres or on agglomeration
971 
972  if (!hasUnblocked && !nConnections && !nProcSets)
973  {
974  // No constraints, possibly weights
975 
976  return
977  (
978  hasWeights
979  ? decompose(mesh, mesh.cellCentres(), cellWeights)
980  : decompose(mesh, mesh.cellCentres())
981  );
982  }
983 
984 
985  // The harder work.
986  // When we have processor sets, connections, or blocked faces.
987 
988 
989  // Determine local regions, separated by blockedFaces
990  regionSplit localRegion(mesh, blockedFace, explicitConnections, false);
991 
992  if (debug)
993  {
994  // Only need to count unblocked faces for debugging
995  const label nUnblocked =
996  (
997  hasUnblocked
998  ? returnReduce
999  (
1000  label(BitOps::count(blockedFace, false)),
1001  sumOp<label>()
1002  )
1003  : 0
1004  );
1005 
1006  Info<< "Constrained decomposition:" << nl
1007  << " faces with same owner and neighbour processor : "
1008  << nUnblocked << nl
1009  << " baffle faces with same owner processor : "
1010  << nConnections << nl
1011  << " faces all on same processor : "
1012  << nProcSets << nl
1013  << " split into " << localRegion.nLocalRegions()
1014  << " regions."
1015  << endl;
1016  }
1017 
1018 
1019  // Gather region weights and determine region cell centres
1020  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1021 
1022  // For the region centre, just take the first cell in the region.
1023  // If we average the region centre instead, cyclics could cause
1024  // the average domain centre to be outside of domain.
1025 
1026  scalarField regionWeights(localRegion.nLocalRegions(), Zero);
1027 
1028  pointField regionCentres(localRegion.nLocalRegions(), point::max);
1029 
1030  if (hasWeights)
1031  {
1032  forAll(localRegion, celli)
1033  {
1034  const label regioni = localRegion[celli];
1035 
1036  regionWeights[regioni] += cellWeights[celli];
1037 
1038  if (regionCentres[regioni] == point::max)
1039  {
1040  regionCentres[regioni] = mesh.cellCentres()[celli];
1041  }
1042  }
1043  }
1044  else
1045  {
1046  forAll(localRegion, celli)
1047  {
1048  const label regioni = localRegion[celli];
1049 
1050  regionWeights[regioni] += 1.0;
1051 
1052  if (regionCentres[regioni] == point::max)
1053  {
1054  regionCentres[regioni] = mesh.cellCentres()[celli];
1055  }
1056  }
1057  }
1058 
1059  // Do decomposition on agglomeration
1060  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1061 
1062  labelList finalDecomp =
1063  decompose
1064  (
1065  mesh,
1066  localRegion,
1067  regionCentres,
1068  regionWeights
1069  );
1070 
1071 
1072  // Apply explicitConnections since decompose did not know about them
1073  for (const labelPair& baffle : explicitConnections)
1074  {
1075  const label f0 = baffle.first();
1076  const label f1 = baffle.second();
1077 
1078  if (!blockedFace[f0] && !blockedFace[f1])
1079  {
1080  // Note: what if internal faces and owner and neighbour on
1081  // different processor?
1082  // So for now just push owner side proc
1083 
1084  const label proci = finalDecomp[mesh.faceOwner()[f0]];
1085 
1086  finalDecomp[mesh.faceOwner()[f1]] = proci;
1087  if (mesh.isInternalFace(f1))
1088  {
1089  finalDecomp[mesh.faceNeighbour()[f1]] = proci;
1090  }
1091  }
1092  else if (blockedFace[f0] != blockedFace[f1])
1093  {
1095  << "On explicit connection between faces " << f0
1096  << " and " << f1
1097  << " the two blockedFace status are not equal : "
1098  << blockedFace[f0] << " and " << blockedFace[f1]
1099  << exit(FatalError);
1100  }
1101  }
1102 
1103 
1104  // blockedFaces corresponding to processor faces need to be handled
1105  // separately since not handled by local regionSplit. We need to
1106  // walk now across coupled faces and make sure to move a whole
1107  // global region across
1108 
1109  // This additionally consolidates/compacts the regions numbers globally,
1110  // since that was skipped in the previous regionSplit.
1111  if (Pstream::parRun())
1112  {
1113  // Re-do regionSplit
1114 
1115  // Field on cells and faces.
1116  List<minData> cellData(mesh.nCells());
1117  List<minData> faceData(mesh.nFaces());
1118 
1119  // Take over blockedFaces by seeding a negative number
1120  // (so is always less than the decomposition)
1121  label nUnblocked = 0;
1122  forAll(blockedFace, facei)
1123  {
1124  if (blockedFace[facei])
1125  {
1126  faceData[facei] = minData(-123);
1127  }
1128  else
1129  {
1130  ++nUnblocked;
1131  }
1132  }
1133 
1134  // Seed unblocked faces with destination processor
1135  labelList seedFaces(nUnblocked);
1136  List<minData> seedData(nUnblocked);
1137  nUnblocked = 0;
1138 
1139  forAll(blockedFace, facei)
1140  {
1141  if (!blockedFace[facei])
1142  {
1143  const label own = mesh.faceOwner()[facei];
1144  seedFaces[nUnblocked] = facei;
1145  seedData[nUnblocked] = minData(finalDecomp[own]);
1146  nUnblocked++;
1147  }
1148  }
1149 
1150 
1151  // Propagate information inwards
1152  FaceCellWave<minData> deltaCalc
1153  (
1154  mesh,
1155  seedFaces,
1156  seedData,
1157  faceData,
1158  cellData,
1160  );
1161 
1162  // And extract
1163  forAll(finalDecomp, celli)
1164  {
1165  if (cellData[celli].valid(deltaCalc.data()))
1166  {
1167  finalDecomp[celli] = cellData[celli].data();
1168  }
1169  }
1170  }
1171 
1172 
1173  // For specifiedProcessorFaces rework the cellToProc to enforce
1174  // all on one processor since we can't guarantee that the input
1175  // to regionSplit was a single region.
1176  // E.g. faceSet 'a' with the cells split into two regions
1177  // by a notch formed by two walls
1178  //
1179  // \ /
1180  // \ /
1181  // ---a----+-----a-----
1182  //
1183  //
1184  // Note that reworking the cellToProc might make the decomposition
1185  // unbalanced.
1186  forAll(specifiedProcessorFaces, seti)
1187  {
1188  const labelList& set = specifiedProcessorFaces[seti];
1189 
1190  label proci = specifiedProcessor[seti];
1191  if (proci == -1)
1192  {
1193  // If no processor specified - use the one from the 0th element
1194  if (set.size())
1195  {
1196  proci = finalDecomp[mesh.faceOwner()[set[0]]];
1197  }
1198  else
1199  {
1200  // Zero-sized processor (e.g. from redistributePar)
1201  proci = 0;
1202  }
1203  }
1204 
1205  for (const label facei : set)
1206  {
1207  const face& f = mesh.faces()[facei];
1208  for (const label pointi : f)
1209  {
1210  const labelList& pFaces = mesh.pointFaces()[pointi];
1211  for (const label pFacei : pFaces)
1212  {
1213  finalDecomp[mesh.faceOwner()[pFacei]] = proci;
1214  if (mesh.isInternalFace(pFacei))
1215  {
1216  finalDecomp[mesh.faceNeighbour()[pFacei]] = proci;
1217  }
1218  }
1219  }
1220  }
1221  }
1222 
1223 
1224  if (debug && Pstream::parRun())
1225  {
1226  labelList nbrDecomp;
1227  syncTools::swapBoundaryCellList(mesh, finalDecomp, nbrDecomp);
1228 
1230  for (const polyPatch& pp : patches)
1231  {
1232  if (pp.coupled())
1233  {
1234  forAll(pp, i)
1235  {
1236  const label facei = pp.start()+i;
1237  const label own = mesh.faceOwner()[facei];
1238  const label bFacei = facei-mesh.nInternalFaces();
1239 
1240  if (!blockedFace[facei])
1241  {
1242  const label ownProc = finalDecomp[own];
1243  const label nbrProc = nbrDecomp[bFacei];
1244 
1245  if (ownProc != nbrProc)
1246  {
1248  << "patch:" << pp.name()
1249  << " face:" << facei
1250  << " at:" << mesh.faceCentres()[facei]
1251  << " ownProc:" << ownProc
1252  << " nbrProc:" << nbrProc
1253  << exit(FatalError);
1254  }
1255  }
1256  }
1257  }
1258  }
1259  }
1260 
1261  return finalDecomp;
1262 }
1263 
1264 
1267  const polyMesh& mesh,
1268  boolList& blockedFace,
1269  PtrList<labelList>& specifiedProcessorFaces,
1270  labelList& specifiedProcessor,
1271  List<labelPair>& explicitConnections
1272 ) const
1273 {
1274  blockedFace.setSize(mesh.nFaces());
1275  blockedFace = true;
1276 
1277  specifiedProcessorFaces.clear();
1278  explicitConnections.clear();
1279 
1280  for (const decompositionConstraint& decompConstraint : constraints_)
1281  {
1282  decompConstraint.add
1283  (
1284  mesh,
1285  blockedFace,
1286  specifiedProcessorFaces,
1287  specifiedProcessor,
1288  explicitConnections
1289  );
1290  }
1291 }
1292 
1293 
1296  const polyMesh& mesh,
1297  const boolList& blockedFace,
1298  const PtrList<labelList>& specifiedProcessorFaces,
1299  const labelList& specifiedProcessor,
1300  const List<labelPair>& explicitConnections,
1301  labelList& decomposition
1302 ) const
1303 {
1304  for (const decompositionConstraint& decompConstraint : constraints_)
1305  {
1306  decompConstraint.apply
1307  (
1308  mesh,
1309  blockedFace,
1310  specifiedProcessorFaces,
1311  specifiedProcessor,
1312  explicitConnections,
1313  decomposition
1314  );
1315  }
1316 }
1317 
1318 
1321  const polyMesh& mesh,
1322  const scalarField& cellWeights
1323 ) const
1324 {
1325  // Collect all constraints
1326 
1327  boolList blockedFace;
1328  PtrList<labelList> specifiedProcessorFaces;
1329  labelList specifiedProcessor;
1330  List<labelPair> explicitConnections;
1331  setConstraints
1332  (
1333  mesh,
1334  blockedFace,
1335  specifiedProcessorFaces,
1336  specifiedProcessor,
1337  explicitConnections
1338  );
1339 
1340 
1341  // Construct decomposition method and either do decomposition on
1342  // cell centres or on agglomeration
1343 
1344  labelList finalDecomp = decompose
1345  (
1346  mesh,
1347  cellWeights, // optional weights
1348  blockedFace, // any cells to be combined
1349  specifiedProcessorFaces,// any whole cluster of cells to be kept
1350  specifiedProcessor,
1351  explicitConnections // baffles
1352  );
1353 
1354 
1355  // Give any constraint the option of modifying the decomposition
1356 
1357  applyConstraints
1358  (
1359  mesh,
1360  blockedFace,
1361  specifiedProcessorFaces,
1362  specifiedProcessor,
1363  explicitConnections,
1364  finalDecomp
1365  );
1366 
1367  return finalDecomp;
1368 }
1369 
1370 
1371 // ************************************************************************* //
Foam::CompactListList::offsets
const List< label > & offsets() const
Return the offset table (= size()+1)
Definition: CompactListListI.H:142
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
BitOps.H
preserveFaceZonesConstraint.H
Foam::CompactListList::m
const List< T > & m() const
Return the packed matrix of data.
Definition: CompactListListI.H:156
Foam::decompositionMethod::calcCellCells
static void calcCellCells(const polyMesh &mesh, const labelList &agglom, const label nLocalCoarse, const bool global, CompactListList< label > &cellCells)
Helper: determine (local or global) cellCells from mesh.
Definition: decompositionMethod.C:517
Foam::decompositionConstraint
Abstract class for handling decomposition constraints.
Definition: decompositionConstraint.H:58
Foam::BitOps::set
void set(List< bool > &bools, const labelRange &range)
Set the specified range 'on' in a boolList.
Definition: BitOps.C:37
Foam::minData
For use with FaceCellWave. Transports minimum passive data.
Definition: minData.H:60
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
Foam::decompositionMethod::optionalRegionDict
static const dictionary & optionalRegionDict(const dictionary &decompDict, const word &regionName)
Return an optional region dictionary from "regions" sub-dictionary.
Definition: decompositionMethod.C:98
Tuple2.H
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::defineRunTimeSelectionTable
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
Foam::CompactListList
A packed storage unstructured matrix of objects of type <T> using an offset table for access.
Definition: polyTopoChange.H:93
Foam::primitiveMesh::nFaces
label nFaces() const
Number of mesh faces.
Definition: primitiveMeshI.H:90
globalIndex.H
Foam::Warning
messageStream Warning
Foam::primitiveMesh::pointFaces
const labelListList & pointFaces() const
Definition: primitiveMeshPointFaces.C:34
Foam::UPstream::parRun
static bool & parRun()
Test if this a parallel run, or allow modify access.
Definition: UPstream.H:434
localPointRegion.H
Foam::globalMeshData::nTotalCells
label nTotalCells() const
Return total number of cells in decomposed mesh.
Definition: globalMeshData.H:371
Foam::syncTools::swapBoundaryFaceList
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:439
Foam::globalIndex::isLocal
bool isLocal(const label i) const
Is on local processor.
Definition: globalIndexI.H:148
Foam::FatalIOError
IOerror FatalIOError
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
decompositionMethod.H
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:81
Foam::decompositionMethod::setConstraints
void setConstraints(const polyMesh &mesh, boolList &blockedFace, PtrList< labelList > &specifiedProcessorFaces, labelList &specifiedProcessor, List< labelPair > &explicitConnections) const
Helper: extract constraints:
Definition: decompositionMethod.C:1266
Foam::HashSet< label, Hash< label > >
syncTools.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::BitOps::all
bool all(const UList< bool > &bools)
True if all entries are 'true' or if the set is empty.
Definition: BitOps.H:84
Foam::sumOp
Definition: ops.H:213
Foam::decompositionConstraint::New
static autoPtr< decompositionConstraint > New(const dictionary &constraintDict)
Return a reference to the selected decompositionConstraint.
Definition: decompositionConstraint.C:64
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::dictionary::null
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition: dictionary.H:385
Foam::dictionary::Searcher
Generic const/non-const dictionary entry searcher.
Definition: dictionary.H:138
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::dictionary::name
const fileName & name() const
The dictionary name.
Definition: dictionary.H:446
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
FatalIOErrorInLookup
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:406
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
Foam::Field< vector >
Foam::CompactListList::setSize
void setSize(const label mRows)
Reset size of CompactListList.
Definition: CompactListList.C:108
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1107
faceSet.H
regionSplit.H
Foam::dictionary::csearch
const_searcher csearch(const word &keyword, enum keyType::option=keyType::REGEX) const
Search dictionary for given keyword.
Definition: dictionarySearch.C:265
singleProcessorFaceSetsConstraint.H
Foam::regionSplit
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:140
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:62
Foam::defaultName
static const word defaultName("coeffs")
preservePatchesConstraint.H
Foam::dictionary::Searcher::dict
dict_reference dict() const
Reference the found entry as a dictionary.
Definition: dictionary.H:241
Foam::syncTools::swapBoundaryCellList
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
Definition: syncToolsTemplates.C:1152
dict
dictionary dict
Definition: searchingEngine.H:14
minData.H
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::primitiveMesh::nBoundaryFaces
label nBoundaryFaces() const
Number of boundary faces (== nFaces - nInternalFaces)
Definition: primitiveMeshI.H:84
Foam::decompositionMethod::nDomains
label nDomains() const
Number of domains.
Definition: decompositionMethod.H:230
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
preserveBafflesConstraint.H
Foam::PtrList::clear
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition: PtrListI.H:97
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::FaceCellWave
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Definition: FaceCellWave.H:78
Foam::globalIndex::toLocal
label toLocal(const label i) const
From global to local on current processor.
Definition: globalIndexI.H:229
Foam::autoPtr< Foam::decompositionMethod >
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:84
Foam::UPstream::msgType
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:541
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
Foam::error::warnAboutAge
static void warnAboutAge(const char *what, const int version)
Emit warning on stderr about something being old.
Definition: error.C:41
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::Pair< label >
Foam::VectorSpace< Vector< Cmpt >, Cmpt, 3 >::max
static const Vector< Cmpt > max
Definition: VectorSpace.H:117
Foam::HashTable::clear
void clear()
Clear all entries from table.
Definition: HashTable.C:630
f
labelList f(nPoints)
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition: BitOps.H:77
Foam::UPstream::worldComm
static label worldComm
Default communicator (all processors)
Definition: UPstream.H:295
Foam::List< label >
Foam::decompositionMethod::decompose
virtual labelList decompose(const pointField &points, const scalarField &pointWeights) const
Return for every coordinate the wanted processor number.
Definition: decompositionMethod.H:244
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
Definition: primitiveMeshI.H:102
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::primitiveMesh::faceCentres
const vectorField & faceCentres() const
Definition: primitiveMeshFaceCentresAndAreas.C:77
FaceCellWave.H
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:115
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:181
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::CompactListList::size
label size() const noexcept
The primary size (the number of rows)
Definition: CompactListListI.H:127
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1295
Foam::decompositionMethod::applyConstraints
void applyConstraints(const polyMesh &mesh, const boolList &blockedFace, const PtrList< labelList > &specifiedProcessorFaces, const labelList &specifiedProcessor, const List< labelPair > &explicitConnections, labelList &finalDecomp) const
Helper: apply constraints to a decomposition.
Definition: decompositionMethod.C:1295
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:122
Foam::orOp
Definition: ops.H:234
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:303
Foam::regionSplit::nLocalRegions
label nLocalRegions() const
Return local number of regions.
Definition: regionSplit.H:288
Foam::decompositionMethod::findCoeffsDict
static const dictionary & findCoeffsDict(const dictionary &dict, const word &coeffsName, int select=selectionType::DEFAULT)
Definition: decompositionMethod.C:229
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1113
Foam::decompositionMethod::New
static autoPtr< decompositionMethod > New(const dictionary &decompDict)
Return a reference to the selected decomposition method.
Definition: decompositionMethod.C:359
Foam::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:417
Foam::globalIndex::toGlobal
label toGlobal(const label i) const
From local to global index.
Definition: globalIndexI.H:164
Foam::primitiveMesh::faceAreas
const vectorField & faceAreas() const
Definition: primitiveMeshFaceCentresAndAreas.C:89