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-2023 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 "globalMeshData.H"
32 #include "syncTools.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 
53 } // End namespace Foam
54 
55 
56 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
57 
58 namespace Foam
59 {
60 
61 // Find named coefficents dictionary, or use default "coeffs"
62 static inline const dictionary* cfindCoeffsDict
63 (
64  const dictionary& dict,
65  const word& coeffsName,
66  const bool allowDefault
67 )
68 {
69  const dictionary* dictptr = dict.findDict(coeffsName);
70  if (!dictptr && allowDefault)
71  {
72  dictptr = dict.findDict("coeffs");
73  }
74  return dictptr;
75 }
76 
77 } // End namespace Foam
78 
79 
80 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
81 
83 (
84  const dictionary& decompDict,
85  const word& regionName
86 )
87 {
88  label nDomainsRegion = 0;
89  label nDomainsGlobal = UPstream::nProcs();
90 
91  // Allow numberOfSubdomains to be optional in parallel, which allows
92  // for missing files on directories that have not yet been created.
93 
94  decompDict.readEntry<label>
95  (
96  "numberOfSubdomains",
97  nDomainsGlobal,
98  keyType::REGEX, // keyType::LITERAL?
100  );
101 
102  if (!regionName.empty())
103  {
104  const dictionary& regionDict =
105  optionalRegionDict(decompDict, regionName);
106 
107  if (regionDict.readIfPresent("numberOfSubdomains", nDomainsRegion))
108  {
109  if (nDomainsRegion >= 1 && nDomainsRegion <= nDomainsGlobal)
110  {
111  return nDomainsRegion;
112  }
113 
115  << "Ignoring region [" << regionName
116  << "] numberOfSubdomains: " << nDomainsRegion
117  << ", using global: " << nDomainsGlobal << nl
118  << endl;
119  }
120  }
121 
122  return nDomainsGlobal;
123 }
124 
125 
127 (
128  const dictionary& decompDict,
129  const word& regionName
130 )
131 {
132  const dictionary* dictptr = nullptr;
133  if
134  (
135  !regionName.empty()
136  && (dictptr = decompDict.findDict("regions")) != nullptr
137  )
138  {
139  dictptr = dictptr->findDict(regionName);
140  }
141  return (dictptr ? *dictptr : dictionary::null);
142 }
143 
144 
145 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
146 
147 bool Foam::decompositionMethod::constraintCompat(const word& modelType) const
148 {
149  bool usable = decompDict_.found(modelType);
150  if (!usable)
151  {
152  return false;
153  }
154 
155  for (const auto& item : constraints_)
156  {
157  if (modelType == item.type())
158  {
159  usable = false;
160  break;
161  }
162  }
163 
164  if (usable)
165  {
166  Warning
167  << nl << " Using '" << modelType
168  << "' constraint specification." << nl;
169  }
170  else
171  {
172  Warning
173  << nl << " Ignoring '" << modelType
174  << "' constraint specification - was already specified." << nl;
175  }
176 
177  // The syntax changed MAY-2014
178  error::warnAboutAge("constraint keyword", 1406);
179 
180  return usable;
181 }
182 
183 
184 void Foam::decompositionMethod::readConstraints()
185 {
186  constraints_.clear();
187 
188  const dictionary* dictptr = decompDict_.findDict("constraints");
189 
190  if (dictptr)
191  {
192  for (const entry& dEntry : *dictptr)
193  {
194  if (!dEntry.isDict()) // safety
195  {
196  // Ignore or warn
197  continue;
198  }
199 
200  const dictionary& dict = dEntry.dict();
201 
202  if (dict.getOrDefault("enabled", true))
203  {
204  constraints_.append(decompositionConstraint::New(dict));
205  }
206  }
207  }
208 
209  // Backwards compatibility (MAY-2014)
210  if (constraintCompat("preserveBaffles"))
211  {
212  constraints_.append
213  (
214  new decompositionConstraints::preserveBaffles()
215  );
216  }
217 
218  if (constraintCompat("preservePatches"))
219  {
220  constraints_.append
221  (
222  new decompositionConstraints::preservePatches
223  (
224  decompDict_.get<wordRes>("preservePatches")
225  )
226  );
227  }
228 
229  if (constraintCompat("preserveFaceZones"))
230  {
231  constraints_.append
232  (
233  new decompositionConstraints::preserveFaceZones
234  (
235  decompDict_.get<wordRes>("preserveFaceZones")
236  )
237  );
238  }
239 
240  if (constraintCompat("singleProcessorFaceSets"))
241  {
242  constraints_.append
243  (
244  new decompositionConstraints::singleProcessorFaceSets
245  (
246  decompDict_.lookup("singleProcessorFaceSets")
247  )
248  );
249  }
250 }
251 
252 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
253 
255 (
256  const dictionary& dict,
257  const word& coeffsName,
258  int select
259 )
260 {
261  const bool allowDefault = !(select & selectionType::EXACT);
262 
263  const dictionary* dictptr =
264  cfindCoeffsDict(dict, coeffsName, allowDefault);
265 
266  if (dictptr)
267  {
268  return *dictptr;
269  }
270 
271  // Not found
272  if (select & selectionType::MANDATORY)
273  {
275  << "'" << coeffsName << "' dictionary not found in dictionary "
276  << dict.name() << endl
277  << abort(FatalIOError);
278  }
279 
280  if (select & selectionType::NULL_DICT)
281  {
282  return dictionary::null;
283  }
284 
285  return dict; // Return original dictionary
286 }
287 
288 
290 (
291  const word& coeffsName,
292  int select
293 ) const
294 {
295  const bool allowDefault = !(select & selectionType::EXACT);
296 
297  const dictionary* dictptr = nullptr;
298 
299  if (!decompRegionDict_.empty())
300  {
301  // Region-specific dictionary
302  dictptr = cfindCoeffsDict(decompRegionDict_, coeffsName, allowDefault);
303  }
304  if (!dictptr)
305  {
306  // General
307  dictptr = cfindCoeffsDict(decompDict_, coeffsName, allowDefault);
308  }
309 
310  if (dictptr)
311  {
312  return *dictptr;
313  }
314 
315  // Not found
316  if (select & selectionType::MANDATORY)
317  {
319  << "'" << coeffsName << "' dictionary not found in dictionary "
320  << decompDict_.name() << endl
321  << abort(FatalIOError);
322  }
323 
324  if (select & selectionType::NULL_DICT)
325  {
326  return dictionary::null;
327  }
329  return decompDict_; // Return general dictionary
330 }
331 
332 
333 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
334 
336 :
337  decompDict_(dictionary::null),
338  decompRegionDict_(dictionary::null),
339  nDomains_(numDomains)
340 {}
341 
342 
344 (
345  const dictionary& decompDict,
346  const word& regionName
347 )
348 :
349  decompDict_(decompDict),
350  decompRegionDict_
351  (
352  optionalRegionDict(decompDict_, regionName)
353  ),
354  nDomains_(nDomains(decompDict, regionName))
355 {
356  readConstraints();
357 }
358 
359 
360 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
361 
363 (
364  const dictionary& decompDict,
365  const word& regionName
366 )
367 {
368  word methodType(decompDict.get<word>("method"));
369 
370  const dictionary& regionDict = optionalRegionDict(decompDict, regionName);
371  regionDict.readIfPresent("method", methodType);
372 
373  auto* ctorPtr = dictionaryConstructorTable(methodType);
374 
375  if (!ctorPtr)
376  {
378  (
379  decompDict,
380  "decompositionMethod",
381  methodType,
382  *dictionaryConstructorTablePtr_
383  ) << exit(FatalIOError);
384  }
385 
386  // verbose
387  {
388  Info<< "Decomposition method " << methodType
389  << " [" << (nDomains(decompDict, regionName)) << ']';
390 
391  if (!regionName.empty())
392  {
393  Info<< " (region " << regionName << ')';
394  }
395  Info<< endl;
396  }
397 
398  return autoPtr<decompositionMethod>(ctorPtr(decompDict, regionName));
399 }
400 
401 
403 (
404  const polyMesh& mesh,
405  const labelList& fineToCoarse,
406  const pointField& coarsePoints,
407  const scalarField& coarseWeights
408 ) const
409 {
410  CompactListList<label> coarseCellCells;
412  (
413  mesh,
414  fineToCoarse,
415  coarsePoints.size(),
416  true, // use global cell labels
417  coarseCellCells
418  );
419 
420  // Decompose based on agglomerated points
421  labelList decomp
422  (
423  decompose
424  (
425  coarseCellCells,
426  coarsePoints,
427  coarseWeights
428  )
429  );
431  // From coarse back to fine for original mesh
432  return labelList(decomp, fineToCoarse);
433 }
434 
435 
437 (
438  const polyMesh& mesh,
439  const labelList& agglom,
440  const label nLocalCoarse,
441  const bool parallel,
442  CompactListList<label>& cellCells
443 )
444 {
446  (
447  mesh,
448  agglom,
449  nLocalCoarse,
450  parallel,
451  cellCells
452  );
453 }
454 
455 
457 (
458  const polyMesh& mesh,
459  const labelList& agglom,
460  const label nLocalCoarse,
461  const bool parallel,
462  CompactListList<label>& cellCells,
463  CompactListList<scalar>& cellCellWeights
464 )
465 {
467  (
468  mesh,
469  agglom,
470  nLocalCoarse,
471  parallel,
472  cellCells,
473  cellCellWeights
474  );
475 }
477 
478 // NOTE:
479 // - alternative calcCellCells that handled explicitConnections was
480 // deactivated (2014 or earlier) and finally removed APR-2018.
481 
483 (
484  const polyMesh& mesh,
485  const scalarField& cellWeights,
486 
487  //- Whether owner and neighbour should be on same processor
488  // (takes priority over explicitConnections)
489  const boolList& blockedFace,
490 
491  //- Whether whole sets of faces (and point neighbours) need to be kept
492  // on single processor
493  const PtrList<labelList>& specifiedProcessorFaces,
494  const labelList& specifiedProcessor,
495 
496  //- Additional connections between boundary faces
497  const List<labelPair>& explicitConnections
498 ) const
499 {
500  // Any weights specified?
501  const bool hasWeights = returnReduceOr(cellWeights.size());
502 
503  if (hasWeights && (cellWeights.size() != mesh.nCells()))
504  {
506  << "Number of weights (" << cellWeights.size()
507  << ") != number of cells (" << mesh.nCells() << ")"
508  << exit(FatalError);
509  }
510 
511  // Any faces not blocked?
512  const bool hasUnblocked =
514  (
515  !blockedFace.empty() && !BitOps::all(blockedFace)
516  );
517 
518 
519  // Any non-mesh connections?
520  const label nConnections = returnReduce
521  (
522  explicitConnections.size(),
523  sumOp<label>()
524  );
525 
526 
527  // Any processor sets?
528  label nProcSets = 0;
529  for (const labelList& procset : specifiedProcessorFaces)
530  {
531  nProcSets += procset.size();
532  }
533  reduce(nProcSets, sumOp<label>());
534 
535 
536  // Either do decomposition on cell centres or on agglomeration
537 
538  if (!hasUnblocked && !nConnections && !nProcSets)
539  {
540  // No constraints, possibly weights
541 
542  return
543  (
544  hasWeights
545  ? decompose(mesh, mesh.cellCentres(), cellWeights)
546  : decompose(mesh, mesh.cellCentres())
547  );
548  }
549 
550 
551  // The harder work.
552  // When we have processor sets, connections, or blocked faces.
553 
554 
555  // Determine local regions, separated by blockedFaces
556  regionSplit localRegion(mesh, blockedFace, explicitConnections, false);
557 
558  if (debug)
559  {
560  // Only need to count unblocked faces for debugging
561  const label nUnblocked =
562  (
563  hasUnblocked
564  ? returnReduce
565  (
566  label(BitOps::count(blockedFace, false)),
567  sumOp<label>()
568  )
569  : 0
570  );
571 
572  Info<< "Constrained decomposition:" << nl
573  << " faces with same owner and neighbour processor : "
574  << nUnblocked << nl
575  << " baffle faces with same owner processor : "
576  << nConnections << nl
577  << " faces all on same processor : "
578  << nProcSets << nl
579  << " split into " << localRegion.nLocalRegions()
580  << " regions."
581  << endl;
582  }
583 
584 
585  // Gather region weights and determine region cell centres
586  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
587 
588  // For the region centre, just take the first cell in the region.
589  // If we average the region centre instead, cyclics could cause
590  // the average domain centre to be outside of domain.
591 
592  scalarField regionWeights(localRegion.nLocalRegions(), Zero);
593 
594  pointField regionCentres(localRegion.nLocalRegions(), point::max);
595 
596  if (hasWeights)
597  {
598  forAll(localRegion, celli)
599  {
600  const label regioni = localRegion[celli];
601 
602  regionWeights[regioni] += cellWeights[celli];
603 
604  if (regionCentres[regioni] == point::max)
605  {
606  regionCentres[regioni] = mesh.cellCentres()[celli];
607  }
608  }
609  }
610  else
611  {
612  forAll(localRegion, celli)
613  {
614  const label regioni = localRegion[celli];
615 
616  regionWeights[regioni] += 1.0;
617 
618  if (regionCentres[regioni] == point::max)
619  {
620  regionCentres[regioni] = mesh.cellCentres()[celli];
621  }
622  }
623  }
624 
625  // Do decomposition on agglomeration
626  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
627 
628  labelList finalDecomp =
629  decompose
630  (
631  mesh,
632  localRegion,
633  regionCentres,
634  regionWeights
635  );
636 
637 
638  // Apply explicitConnections since decompose did not know about them
639  for (const labelPair& baffle : explicitConnections)
640  {
641  const label f0 = baffle.first();
642  const label f1 = baffle.second();
643 
644  if (!blockedFace[f0] && !blockedFace[f1])
645  {
646  // Note: what if internal faces and owner and neighbour on
647  // different processor?
648  // So for now just push owner side proc
649 
650  const label proci = finalDecomp[mesh.faceOwner()[f0]];
651 
652  finalDecomp[mesh.faceOwner()[f1]] = proci;
653  if (mesh.isInternalFace(f1))
654  {
655  finalDecomp[mesh.faceNeighbour()[f1]] = proci;
656  }
657  }
658  else if (blockedFace[f0] != blockedFace[f1])
659  {
661  << "On explicit connection between faces " << f0
662  << " and " << f1
663  << " the two blockedFace status are not equal : "
664  << blockedFace[f0] << " and " << blockedFace[f1]
665  << exit(FatalError);
666  }
667  }
668 
669 
670  // blockedFaces corresponding to processor faces need to be handled
671  // separately since not handled by local regionSplit. We need to
672  // walk now across coupled faces and make sure to move a whole
673  // global region across
674 
675  // This additionally consolidates/compacts the regions numbers globally,
676  // since that was skipped in the previous regionSplit.
677  if (Pstream::parRun())
678  {
679  // Re-do regionSplit
680 
681  // Field on cells and faces.
682  List<minData> cellData(mesh.nCells());
683  List<minData> faceData(mesh.nFaces());
684 
685  // Take over blockedFaces by seeding a negative number
686  // (so is always less than the decomposition)
687  label nUnblocked = 0;
688  forAll(blockedFace, facei)
689  {
690  if (blockedFace[facei])
691  {
692  faceData[facei] = minData(-123);
693  }
694  else
695  {
696  ++nUnblocked;
697  }
698  }
699 
700  // Seed unblocked faces with destination processor
701  labelList seedFaces(nUnblocked);
702  List<minData> seedData(nUnblocked);
703  nUnblocked = 0;
704 
705  forAll(blockedFace, facei)
706  {
707  if (!blockedFace[facei])
708  {
709  const label own = mesh.faceOwner()[facei];
710  seedFaces[nUnblocked] = facei;
711  seedData[nUnblocked] = minData(finalDecomp[own]);
712  nUnblocked++;
713  }
714  }
715 
716 
717  // Propagate information inwards
718  FaceCellWave<minData> deltaCalc
719  (
720  mesh,
721  seedFaces,
722  seedData,
723  faceData,
724  cellData,
726  );
727 
728  // And extract
729  forAll(finalDecomp, celli)
730  {
731  if (cellData[celli].valid(deltaCalc.data()))
732  {
733  finalDecomp[celli] = cellData[celli].data();
734  }
735  }
736  }
737 
738 
739  // For specifiedProcessorFaces rework the cellToProc to enforce
740  // all on one processor since we can't guarantee that the input
741  // to regionSplit was a single region.
742  // E.g. faceSet 'a' with the cells split into two regions
743  // by a notch formed by two walls
744  //
745  // \ /
746  // \ /
747  // ---a----+-----a-----
748  //
749  //
750  // Note that reworking the cellToProc might make the decomposition
751  // unbalanced.
752  forAll(specifiedProcessorFaces, seti)
753  {
754  const labelList& set = specifiedProcessorFaces[seti];
755 
756  label proci = specifiedProcessor[seti];
757  if (proci == -1)
758  {
759  // If no processor specified - use the one from the 0th element
760  if (set.size())
761  {
762  proci = finalDecomp[mesh.faceOwner()[set[0]]];
763  }
764  else
765  {
766  // Zero-sized processor (e.g. from redistributePar)
767  proci = 0;
768  }
769  }
770 
771  for (const label facei : set)
772  {
773  const face& f = mesh.faces()[facei];
774  for (const label pointi : f)
775  {
776  const labelList& pFaces = mesh.pointFaces()[pointi];
777  for (const label pFacei : pFaces)
778  {
779  finalDecomp[mesh.faceOwner()[pFacei]] = proci;
780  if (mesh.isInternalFace(pFacei))
781  {
782  finalDecomp[mesh.faceNeighbour()[pFacei]] = proci;
783  }
784  }
785  }
786  }
787  }
788 
789 
790  if (debug && Pstream::parRun())
791  {
792  labelList nbrDecomp;
793  syncTools::swapBoundaryCellList(mesh, finalDecomp, nbrDecomp);
794 
796  for (const polyPatch& pp : patches)
797  {
798  if (pp.coupled())
799  {
800  forAll(pp, i)
801  {
802  const label facei = pp.start()+i;
803  const label own = mesh.faceOwner()[facei];
804  const label bFacei = facei-mesh.nInternalFaces();
805 
806  if (!blockedFace[facei])
807  {
808  const label ownProc = finalDecomp[own];
809  const label nbrProc = nbrDecomp[bFacei];
810 
811  if (ownProc != nbrProc)
812  {
814  << "patch:" << pp.name()
815  << " face:" << facei
816  << " at:" << mesh.faceCentres()[facei]
817  << " ownProc:" << ownProc
818  << " nbrProc:" << nbrProc
819  << exit(FatalError);
820  }
821  }
822  }
823  }
824  }
825  }
826 
827  return finalDecomp;
828 }
829 
830 
832 (
833  const polyMesh& mesh,
834  boolList& blockedFace,
835  PtrList<labelList>& specifiedProcessorFaces,
836  labelList& specifiedProcessor,
837  List<labelPair>& explicitConnections
838 ) const
839 {
840  blockedFace.resize_nocopy(mesh.nFaces());
841  blockedFace = true;
842 
843  specifiedProcessorFaces.clear();
844  explicitConnections.clear();
845 
846  for (const decompositionConstraint& decompConstraint : constraints_)
847  {
848  decompConstraint.add
849  (
850  mesh,
851  blockedFace,
852  specifiedProcessorFaces,
853  specifiedProcessor,
854  explicitConnections
855  );
856  }
857 }
858 
859 
861 (
862  const polyMesh& mesh,
863  const boolList& blockedFace,
864  const PtrList<labelList>& specifiedProcessorFaces,
865  const labelList& specifiedProcessor,
866  const List<labelPair>& explicitConnections,
867  labelList& decomposition
868 ) const
869 {
870  for (const decompositionConstraint& decompConstraint : constraints_)
871  {
872  decompConstraint.apply
873  (
874  mesh,
875  blockedFace,
876  specifiedProcessorFaces,
877  specifiedProcessor,
878  explicitConnections,
879  decomposition
880  );
881  }
882 }
883 
884 
886 (
887  const polyMesh& mesh,
888  const scalarField& cellWeights
889 ) const
890 {
891  // Collect all constraints
892 
893  boolList blockedFace;
894  PtrList<labelList> specifiedProcessorFaces;
895  labelList specifiedProcessor;
896  List<labelPair> explicitConnections;
897  setConstraints
898  (
899  mesh,
900  blockedFace,
901  specifiedProcessorFaces,
902  specifiedProcessor,
903  explicitConnections
904  );
905 
906 
907  // Construct decomposition method and either do decomposition on
908  // cell centres or on agglomeration
909 
910  labelList finalDecomp = decompose
911  (
912  mesh,
913  cellWeights, // optional weights
914  blockedFace, // any cells to be combined
915  specifiedProcessorFaces,// any whole cluster of cells to be kept
916  specifiedProcessor,
917  explicitConnections // baffles
918  );
919 
920 
921  // Give any constraint the option of modifying the decomposition
922 
923  applyConstraints
924  (
925  mesh,
926  blockedFace,
927  specifiedProcessorFaces,
928  specifiedProcessor,
929  explicitConnections,
930  finalDecomp
931  );
932 
933  return finalDecomp;
934 }
935 
936 
937 // * * * * * * * * * * * * * * * Stub Functions * * * * * * * * * * * * * * //
938 
940 (
942  const scalarField& pointWeights
943 ) const
944 {
946  return labelList();
947 }
948 
949 
950 // ************************************************************************* //
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:136
Abstract class for handling decomposition constraints.
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
static void calcCellCells(const polyMesh &mesh, const labelList &agglom, const label nLocalCoarse, const bool parallel, CompactListList< label > &cellCells)
Determine (local or global) cellCells from mesh agglomeration.
label nLocalRegions() const
Return local number of regions.
Definition: regionSplit.H:320
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
List< bool > select(const label n, const labelUList &locations)
Construct a selection list of bools (all false) with the given pre-size, subsequently add specified l...
Definition: BitOps.C:134
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:666
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:272
static void calcCellCells(const polyMesh &mesh, const labelList &agglom, const label nLocalCoarse, const bool parallel, CompactListList< label > &cellCells)
Determine (local or global) cellCells from mesh agglomeration.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Definition: FaceCellWave.H:206
void setConstraints(const polyMesh &mesh, boolList &blockedFace, PtrList< labelList > &specifiedProcessorFaces, labelList &specifiedProcessor, List< labelPair > &explicitConnections) const
Helper: extract constraints:
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:175
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
label nFaces() const noexcept
Number of mesh faces.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
const fileName & name() const noexcept
The dictionary name.
Definition: dictionaryI.H:41
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
static bool warnAboutAge(const int version) noexcept
Test if an age warning should be emitted.
Definition: error.C:67
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static autoPtr< decompositionConstraint > New(const dictionary &constraintDict)
Return a reference to the selected decompositionConstraint.
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.
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect...
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:342
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1065
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
const pointField & points
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:137
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:608
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition: dictionary.H:474
const globalMeshData & globalData() const
Return parallel info (demand-driven)
Definition: polyMesh.C:1311
label nInternalFaces() const noexcept
Number of internal faces.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
const vectorField & cellCentres() const
errorManip< error > abort(error &err)
Definition: errorManip.H:139
static const dictionary & findCoeffsDict(const dictionary &dict, const word &coeffsName, int select=selectionType::DEFAULT)
Locate coeffsName dictionary or the fallback "coeffs" dictionary within an enclosing dictionary...
label nDomains() const noexcept
Number of domains.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
A packed storage of objects of type <T> using an offset table for access.
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
int debug
Static debugging option.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
label nTotalCells() const noexcept
Return total number of cells in decomposed mesh.
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].reset(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
decompositionMethod(const label numDomains)
Construct with specified number of domains, no coefficients or constraints.
messageStream Warning
Warning stream (stdout output on master, null elsewhere), with additional &#39;FOAM Warning&#39; header text...
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
const vectorField & faceCentres() const
static autoPtr< decompositionMethod > New(const dictionary &decompDict, const word &regionName="")
Return a reference to the selected decomposition method, optionally region-specific.
#define WarningInFunction
Report a warning using Foam::Warning.
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
label nCells() const noexcept
Number of mesh cells.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
const polyBoundaryMesh & patches
static const dictionary & optionalRegionDict(const dictionary &decompDict, const word &regionName)
Return an optional region-specific dictionary from "regions" sub-dictionary, or dictionary::null on f...
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
bool all(const UList< bool > &bools)
True if all entries are &#39;true&#39; or if the set is empty.
Definition: BitOps.H:83
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition: PtrListI.H:81
messageStream Info
Information stream (stdout output on master, null elsewhere)
const labelListList & pointFaces() const
static const dictionary * cfindCoeffsDict(const dictionary &dict, const word &coeffsName, const bool allowDefault)
Reading is optional [identical to READ_IF_PRESENT].
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
List< label > labelList
A List of labels.
Definition: List.H:62
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
For use with FaceCellWave. Transports minimum passive data.
Definition: minData.H:56
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:686
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:635
Regular expression.
Definition: keyType.H:83
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
virtual labelList decompose(const pointField &points, const scalarField &pointWeights=scalarField::null()) const
Return the wanted processor number for every coordinate, using uniform or specified point weights...
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and a sub-dictionary) otherwise return nullptr...
Definition: dictionaryI.H:124
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127