ptscotchDecomp.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-2017 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 "ptscotchDecomp.H"
31 #include "Time.H"
32 #include "OFstream.H"
33 #include "globalIndex.H"
34 #include "SubField.H"
35 
36 // Avoid too many warnings from mpi.h
37 #pragma GCC diagnostic ignored "-Wold-style-cast"
38 
39 #include <cstdio>
40 #include <mpi.h>
41 #include "ptscotch.h"
42 
43 // Hack: scotch generates floating point errors so need to switch off error
44 // trapping!
45 #ifdef __GLIBC__
46  #ifndef _GNU_SOURCE
47  #define _GNU_SOURCE
48  #endif
49  #include <fenv.h>
50 #endif
51 
52 // Provide a clear error message if we have a size mismatch
53 static_assert
54 (
55  sizeof(Foam::label) == sizeof(SCOTCH_Num),
56  "sizeof(Foam::label) == sizeof(SCOTCH_Num), check your scotch headers"
57 );
58 
59 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
60 
61 namespace Foam
62 {
63  defineTypeNameAndDebug(ptscotchDecomp, 0);
64 
66  (
67  decompositionMethod,
68  ptscotchDecomp,
69  dictionary
70  );
71 
73  (
74  decompositionMethod,
75  ptscotchDecomp,
76  dictionaryRegion
77  );
78 }
79 
80 
81 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
82 
83 void Foam::ptscotchDecomp::graphPath(const polyMesh& mesh) const
84 {
85  graphPath_ = mesh.time().path()/mesh.name();
86 }
87 
88 
89 void Foam::ptscotchDecomp::check(const int retVal, const char* str)
90 {
91  if (retVal)
92  {
94  << "Call to scotch routine " << str << " failed.\n"
95  << exit(FatalError);
96  }
97 }
98 
99 
101 //Foam::label Foam::ptscotchDecomp::decomposeZeroDomains
102 //(
103 // const labelList& initadjncy,
104 // const labelList& initxadj,
105 // const List<scalar>& initcWeights,
106 // labelList& finalDecomp
107 //) const
108 //{
109 // globalIndex globalCells(initxadj.size()-1);
110 //
111 // bool hasZeroDomain = false;
112 // for (const int proci : Pstream::allProcs())
113 // {
114 // if (globalCells.localSize(proci) == 0)
115 // {
116 // hasZeroDomain = true;
117 // break;
118 // }
119 // }
120 //
121 // if (!hasZeroDomain)
122 // {
123 // return decompose
124 // (
125 // initadjncy,
126 // initxadj,
127 // initcWeights,
128 // finalDecomp
129 // );
130 // }
131 //
132 //
133 // if (debug)
134 // {
135 // Info<< "ptscotchDecomp : have graphs with locally 0 cells."
136 // << " trickling down." << endl;
137 // }
138 //
139 // // Make sure every domain has at least one cell
140 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
141 // // (scotch does not like zero sized domains)
142 // // Trickle cells from processors that have them up to those that
143 // // don't.
144 //
145 //
146 // // Number of cells to send to the next processor
147 // // (is same as number of cells next processor has to receive)
148 // List<label> nSendCells(Pstream::nProcs(), Zero);
149 //
150 // for (label proci = nSendCells.size()-1; proci >=1; proci--)
151 // {
152 // label nLocalCells = globalCells.localSize(proci);
153 // if (nLocalCells-nSendCells[proci] < 1)
154 // {
155 // nSendCells[proci-1] = nSendCells[proci]-nLocalCells+1;
156 // }
157 // }
158 //
159 // // First receive (so increasing the sizes of all arrays)
160 //
161 // Field<int> xadj(initxadj);
162 // Field<int> adjncy(initadjncy);
163 // scalarField cWeights(initcWeights);
164 //
165 // if (Pstream::myProcNo() >= 1 && nSendCells[Pstream::myProcNo()-1] > 0)
166 // {
167 // // Receive cells from previous processor
168 // IPstream fromPrevProc(Pstream::commsTypes::blocking,
169 // Pstream::myProcNo()-1);
170 //
171 // Field<int> prevXadj(fromPrevProc);
172 // Field<int> prevAdjncy(fromPrevProc);
173 // scalarField prevCellWeights(fromPrevProc);
174 //
175 // if (prevXadj.size() != nSendCells[Pstream::myProcNo()-1])
176 // {
177 // FatalErrorInFunction
178 // << "Expected from processor " << Pstream::myProcNo()-1
179 // << " connectivity for " << nSendCells[Pstream::myProcNo()-1]
180 // << " nCells but only received " << prevXadj.size()
181 // << abort(FatalError);
182 // }
183 //
184 // // Insert adjncy
185 // prepend(prevAdjncy, adjncy);
186 // // Adapt offsets and prepend xadj
187 // xadj += prevAdjncy.size();
188 // prepend(prevXadj, xadj);
189 // // Weights
190 // prepend(prevCellWeights, cWeights);
191 // }
192 //
193 //
194 // // Send to my next processor
195 //
196 // if (nSendCells[Pstream::myProcNo()] > 0)
197 // {
198 // // Send cells to next processor
199 // OPstream toNextProc(Pstream::commsTypes::blocking,
200 // Pstream::myProcNo()+1);
201 //
202 // label nCells = nSendCells[Pstream::myProcNo()];
203 // label startCell = xadj.size()-1 - nCells;
204 // label startFace = xadj[startCell];
205 // label nFaces = adjncy.size()-startFace;
206 //
207 // // Send for all cell data: last nCells elements
208 // // Send for all face data: last nFaces elements
209 // toNextProc
210 // << Field<int>::subField(xadj, nCells, startCell)-startFace
211 // << Field<int>::subField(adjncy, nFaces, startFace)
212 // <<
213 // (
214 // cWeights.size()
215 // ? static_cast<const scalarField&>
216 // (
217 // scalarField::subField(cWeights, nCells, startCell)
218 // )
219 // : scalarField(0)
220 // );
221 //
222 // // Remove data that has been sent
223 // if (cWeights.size())
224 // {
225 // cWeights.setSize(cWeights.size()-nCells);
226 // }
227 // adjncy.setSize(adjncy.size()-nFaces);
228 // xadj.setSize(xadj.size() - nCells);
229 // }
230 //
231 //
232 // // Do decomposition as normal. Sets finalDecomp.
233 // label result = decompose(adjncy, xadj, cWeights, finalDecomp);
234 //
235 //
236 // if (debug)
237 // {
238 // Info<< "ptscotchDecomp : have graphs with locally 0 cells."
239 // << " trickling up." << endl;
240 // }
241 //
242 //
243 // // If we sent cells across make sure we undo it
244 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
245 //
246 // // Receive back from next processor if I sent something
247 // if (nSendCells[Pstream::myProcNo()] > 0)
248 // {
249 // IPstream fromNextProc(Pstream::commsTypes::blocking,
250 // Pstream::myProcNo()+1);
251 //
252 // List<label> nextFinalDecomp(fromNextProc);
253 //
254 // if (nextFinalDecomp.size() != nSendCells[Pstream::myProcNo()])
255 // {
256 // FatalErrorInFunction
257 // << "Expected from processor " << Pstream::myProcNo()+1
258 // << " decomposition for " << nSendCells[Pstream::myProcNo()]
259 // << " nCells but only received " << nextFinalDecomp.size()
260 // << abort(FatalError);
261 // }
262 //
263 // append(nextFinalDecomp, finalDecomp);
264 // }
265 //
266 // // Send back to previous processor.
267 // if (Pstream::myProcNo() >= 1 && nSendCells[Pstream::myProcNo()-1] > 0)
268 // {
269 // OPstream toPrevProc(Pstream::commsTypes::blocking,
270 // Pstream::myProcNo()-1);
271 //
272 // label nToPrevious = nSendCells[Pstream::myProcNo()-1];
273 //
274 // toPrevProc <<
275 // SubList<label>
276 // (
277 // finalDecomp,
278 // nToPrevious,
279 // finalDecomp.size()-nToPrevious
280 // );
281 //
282 // // Remove locally what has been sent
283 // finalDecomp.setSize(finalDecomp.size()-nToPrevious);
284 // }
285 // return result;
286 //}
287 
288 
289 Foam::label Foam::ptscotchDecomp::decompose
290 (
291  const labelList& adjncy,
292  const labelList& xadj,
293  const List<scalar>& cWeights,
294  labelList& finalDecomp
295 ) const
296 {
297  List<label> dummyAdjncy;
298  List<label> dummyXadj;
299 
300  return decompose
301  (
302  adjncy.size(),
303  (adjncy.size() ? adjncy.begin() : dummyAdjncy.begin()),
304  xadj.size(),
305  (xadj.size() ? xadj.begin() : dummyXadj.begin()),
306  cWeights,
307  finalDecomp
308  );
309 }
310 
311 
312 Foam::label Foam::ptscotchDecomp::decompose
313 (
314  const label adjncySize,
315  const label adjncy[],
316  const label xadjSize,
317  const label xadj[],
318  const List<scalar>& cWeights,
319  labelList& finalDecomp
320 ) const
321 {
322  if (debug)
323  {
324  Pout<< "ptscotchDecomp : entering with xadj:" << xadjSize << endl;
325  }
326 
327  // Dump graph
328  if (coeffsDict_.getOrDefault("writeGraph", false))
329  {
330  OFstream str
331  (
332  graphPath_ + "_" + Foam::name(Pstream::myProcNo()) + ".dgr"
333  );
334 
335  Pout<< "Dumping Scotch graph file to " << str.name() << endl
336  << "Use this in combination with dgpart." << endl;
337 
338  globalIndex globalCells(xadjSize-1);
339 
340  // Distributed graph file (.grf)
341  const label version = 2;
342  str << version << nl;
343  // Number of files (procglbnbr)
344  str << Pstream::nProcs();
345  // My file number (procloc)
346  str << ' ' << Pstream::myProcNo() << nl;
347 
348  // Total number of vertices (vertglbnbr)
349  str << globalCells.size();
350  // Total number of connections (edgeglbnbr)
351  str << ' ' << returnReduce(xadj[xadjSize-1], sumOp<label>()) << nl;
352  // Local number of vertices (vertlocnbr)
353  str << xadjSize-1;
354  // Local number of connections (edgelocnbr)
355  str << ' ' << xadj[xadjSize-1] << nl;
356  // Numbering starts from 0
357  label baseval = 0;
358  // 100*hasVertlabels+10*hasEdgeWeights+1*hasVertWeighs
359  str << baseval << ' ' << "000" << nl;
360  for (label celli = 0; celli < xadjSize-1; celli++)
361  {
362  const label start = xadj[celli];
363  const label end = xadj[celli+1];
364 
365  str << end-start; // size
366 
367  for (label i = start; i < end; i++)
368  {
369  str << ' ' << adjncy[i];
370  }
371  str << nl;
372  }
373  }
374 
375 
376  // Make repeatable
377  SCOTCH_randomReset();
378 
379  // Strategy
380  // ~~~~~~~~
381 
382  // Default.
383  SCOTCH_Strat stradat;
384  check(SCOTCH_stratInit(&stradat), "SCOTCH_stratInit");
385 
386  string strategy;
387  if (coeffsDict_.readIfPresent("strategy", strategy))
388  {
389  if (debug)
390  {
391  Info<< "ptscotchDecomp : Using strategy " << strategy << endl;
392  }
393  SCOTCH_stratDgraphMap(&stradat, strategy.c_str());
394  //fprintf(stdout, "S\tStrat=");
395  //SCOTCH_stratSave(&stradat, stdout);
396  //fprintf(stdout, "\n");
397  }
398 
399  // Graph
400  // ~~~~~
401 
402  List<label> velotab;
403 
404 
405  // Check for externally provided cellweights and if so initialise weights
406 
407  const scalar minWeights = gMin(cWeights);
408  const scalar maxWeights = gMax(cWeights);
409 
410  if (maxWeights > minWeights)
411  {
412  if (minWeights <= 0)
413  {
415  << "Illegal minimum weight " << minWeights
416  << endl;
417  }
418 
419  if (cWeights.size() != xadjSize-1)
420  {
422  << "Number of cell weights " << cWeights.size()
423  << " does not equal number of cells " << xadjSize-1
424  << exit(FatalError);
425  }
426  }
427 
428  scalar velotabSum = gSum(cWeights)/minWeights;
429 
430  scalar rangeScale(1.0);
431 
432  if (Pstream::master())
433  {
434  if (velotabSum > scalar(labelMax - 1))
435  {
436  // 0.9 factor of safety to avoid floating point round-off in
437  // rangeScale tipping the subsequent sum over the integer limit.
438  rangeScale = 0.9*scalar(labelMax - 1)/velotabSum;
439 
441  << "Sum of weights has overflowed integer: " << velotabSum
442  << ", compressing weight scale by a factor of " << rangeScale
443  << endl;
444  }
445  }
446 
447  Pstream::scatter(rangeScale);
448 
449  if (maxWeights > minWeights)
450  {
451  if (cWeights.size())
452  {
453  // Convert to integers.
454  velotab.setSize(cWeights.size());
455 
456  forAll(velotab, i)
457  {
458  velotab[i] = int((cWeights[i]/minWeights - 1)*rangeScale) + 1;
459  }
460  }
461  else
462  {
463  // Locally zero cells but not globally. Make sure we have
464  // some size so .begin() does not return null pointer. Data
465  // itself is never used.
466  velotab.setSize(1);
467  velotab[0] = 1;
468  }
469  }
470 
471 
472  if (debug)
473  {
474  Pout<< "SCOTCH_dgraphInit" << endl;
475  }
476  SCOTCH_Dgraph grafdat;
477  check(SCOTCH_dgraphInit(&grafdat, MPI_COMM_WORLD), "SCOTCH_dgraphInit");
478 
479 
480  if (debug)
481  {
482  Pout<< "SCOTCH_dgraphBuild with:" << nl
483  << "xadjSize-1 : " << xadjSize-1 << nl
484  << "xadj : " << name(xadj) << nl
485  << "velotab : " << name(velotab.begin()) << nl
486  << "adjncySize : " << adjncySize << nl
487  << "adjncy : " << name(adjncy) << nl
488  << endl;
489  }
490 
491  check
492  (
493  SCOTCH_dgraphBuild
494  (
495  &grafdat, // grafdat
496  0, // baseval, c-style numbering
497  xadjSize-1, // vertlocnbr, nCells
498  xadjSize-1, // vertlocmax
499  const_cast<SCOTCH_Num*>(xadj),
500  // vertloctab, start index per cell into
501  // adjncy
502  const_cast<SCOTCH_Num*>(xadj+1),// vendloctab, end index ,,
503 
504  const_cast<SCOTCH_Num*>(velotab.begin()),// veloloctab, vtx weights
505  nullptr, // vlblloctab
506 
507  adjncySize, // edgelocnbr, number of arcs
508  adjncySize, // edgelocsiz
509  const_cast<SCOTCH_Num*>(adjncy), // edgeloctab
510  nullptr, // edgegsttab
511  nullptr // edlotab, edge weights
512  ),
513  "SCOTCH_dgraphBuild"
514  );
515 
516 
517  if (debug)
518  {
519  Pout<< "SCOTCH_dgraphCheck" << endl;
520  }
521  check(SCOTCH_dgraphCheck(&grafdat), "SCOTCH_dgraphCheck");
522 
523 
524  // Architecture
525  // ~~~~~~~~~~~~
526  // (fully connected network topology since using switch)
527 
528  if (debug)
529  {
530  Pout<< "SCOTCH_archInit" << endl;
531  }
532  SCOTCH_Arch archdat;
533  check(SCOTCH_archInit(&archdat), "SCOTCH_archInit");
534 
535  List<label> processorWeights;
536  if
537  (
538  coeffsDict_.readIfPresent("processorWeights", processorWeights)
539  && processorWeights.size()
540  )
541  {
542  if (debug)
543  {
544  Info<< "ptscotchDecomp : Using procesor weights "
545  << processorWeights
546  << endl;
547  }
548 
549  if (processorWeights.size() != nDomains_)
550  {
551  FatalIOErrorInFunction(coeffsDict_)
552  << "processorWeights not the same size"
553  << " as the wanted number of domains " << nDomains_
554  << exit(FatalIOError);
555  }
556 
557  check
558  (
559  SCOTCH_archCmpltw
560  (
561  &archdat, nDomains_, processorWeights.begin()
562  ),
563  "SCOTCH_archCmpltw"
564  );
565  }
566  else
567  {
568  if (debug)
569  {
570  Pout<< "SCOTCH_archCmplt" << endl;
571  }
572  check
573  (
574  SCOTCH_archCmplt(&archdat, nDomains_),
575  "SCOTCH_archCmplt"
576  );
577  }
578 
579 
580  // Hack:switch off fpu error trapping
581  #ifdef FE_NOMASK_ENV
582  int oldExcepts = fedisableexcept
583  (
584  FE_DIVBYZERO
585  | FE_INVALID
586  | FE_OVERFLOW
587  );
588  #endif
589 
590 
591  // Note: always provide allocated storage even if local size 0
592  finalDecomp.setSize(max(1, xadjSize-1));
593  finalDecomp = 0;
594 
595  if (debug)
596  {
597  Pout<< "SCOTCH_dgraphMap" << endl;
598  }
599  check
600  (
601  SCOTCH_dgraphMap
602  (
603  &grafdat,
604  &archdat,
605  &stradat, // const SCOTCH_Strat *
606  finalDecomp.begin() // parttab
607  ),
608  "SCOTCH_graphMap"
609  );
610 
611  #ifdef FE_NOMASK_ENV
612  feenableexcept(oldExcepts);
613  #endif
614 
615  // See above note to have size 1. Undo.
616  finalDecomp.setSize(xadjSize-1);
617 
618  //check
619  //(
620  // SCOTCH_dgraphPart
621  // (
622  // &grafdat,
623  // nDomains_, // partnbr
624  // &stradat, // const SCOTCH_Strat *
625  // finalDecomp.begin() // parttab
626  // ),
627  // "SCOTCH_graphPart"
628  //);
629 
630  if (debug)
631  {
632  Pout<< "SCOTCH_dgraphExit" << endl;
633  }
634  // Release storage for graph
635  SCOTCH_dgraphExit(&grafdat);
636  // Release storage for strategy
637  SCOTCH_stratExit(&stradat);
638  // Release storage for network topology
639  SCOTCH_archExit(&archdat);
640 
641  return 0;
642 }
643 
644 
645 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
646 
647 Foam::ptscotchDecomp::ptscotchDecomp(const dictionary& decompDict)
648 :
649  decompositionMethod(decompDict),
650  coeffsDict_(findCoeffsDict("scotchCoeffs", selectionType::NULL_DICT))
651 {}
652 
653 
654 Foam::ptscotchDecomp::ptscotchDecomp
655 (
656  const dictionary& decompDict,
657  const word& regionName
658 )
659 :
660  decompositionMethod(decompDict, regionName),
661  coeffsDict_(findCoeffsDict("scotchCoeffs", selectionType::NULL_DICT))
662 {}
663 
664 
665 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
666 
667 Foam::labelList Foam::ptscotchDecomp::decompose
668 (
669  const polyMesh& mesh,
670  const pointField& points,
671  const scalarField& pointWeights
672 ) const
673 {
674  // Where to write graph
675  graphPath(mesh);
676 
677  if (points.size() != mesh.nCells())
678  {
680  << "Can use this decomposition method only for the whole mesh"
681  << endl
682  << "and supply one coordinate (cellCentre) for every cell." << endl
683  << "The number of coordinates " << points.size() << endl
684  << "The number of cells in the mesh " << mesh.nCells()
685  << exit(FatalError);
686  }
687 
688 
689  // Make Metis CSR (Compressed Storage Format) storage
690  // adjncy : contains neighbours (= edges in graph)
691  // xadj(celli) : start of information in adjncy for celli
692 
693  CompactListList<label> cellCells;
694  calcCellCells
695  (
696  mesh,
697  identity(mesh.nCells()),
698  mesh.nCells(),
699  true,
700  cellCells
701  );
702 
703  // Decompose using default weights
704  labelList decomp;
705  decompose
706  (
707  cellCells.m(),
708  cellCells.offsets(),
709  pointWeights,
710  decomp
711  );
712 
713  return decomp;
714 }
715 
716 
717 Foam::labelList Foam::ptscotchDecomp::decompose
718 (
719  const polyMesh& mesh,
720  const labelList& agglom,
721  const pointField& agglomPoints,
722  const scalarField& pointWeights
723 ) const
724 {
725  // Where to write graph
726  graphPath(mesh);
727 
728  if (agglom.size() != mesh.nCells())
729  {
731  << "Size of cell-to-coarse map " << agglom.size()
732  << " differs from number of cells in mesh " << mesh.nCells()
733  << exit(FatalError);
734  }
735 
736 
737  // Make Metis CSR (Compressed Storage Format) storage
738  // adjncy : contains neighbours (= edges in graph)
739  // xadj(celli) : start of information in adjncy for celli
740  CompactListList<label> cellCells;
741  calcCellCells
742  (
743  mesh,
744  agglom,
745  agglomPoints.size(),
746  true,
747  cellCells
748  );
749 
750  // Decompose using weights
751  labelList decomp;
752  decompose
753  (
754  cellCells.m(),
755  cellCells.offsets(),
756  pointWeights,
757  decomp
758  );
759 
760  // Rework back into decomposition for original mesh
761  labelList fineDistribution(agglom.size());
762 
763  forAll(fineDistribution, i)
764  {
765  fineDistribution[i] = decomp[agglom[i]];
766  }
767 
768  return fineDistribution;
769 }
770 
771 
772 Foam::labelList Foam::ptscotchDecomp::decompose
773 (
774  const labelListList& globalCellCells,
775  const pointField& cellCentres,
776  const scalarField& cWeights
777 ) const
778 {
779  // Where to write graph
780  graphPath_ = "ptscotch";
781 
782  if (cellCentres.size() != globalCellCells.size())
783  {
785  << "Inconsistent number of cells (" << globalCellCells.size()
786  << ") and number of cell centres (" << cellCentres.size()
787  << ")." << exit(FatalError);
788  }
789 
790 
791  // Make Metis CSR (Compressed Storage Format) storage
792  // adjncy : contains neighbours (= edges in graph)
793  // xadj(celli) : start of information in adjncy for celli
794 
795  CompactListList<label> cellCells(globalCellCells);
796 
797  // Decompose using weights
798  labelList decomp;
799  decompose
800  (
801  cellCells.m(),
802  cellCells.offsets(),
803  cWeights,
804  decomp
805  );
806 
807  return decomp;
808 }
809 
810 
811 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::HashTable::size
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::labelMax
constexpr label labelMax
Definition: label.H:61
SubField.H
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
globalIndex.H
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Am I the master process.
Definition: UPstream.H:458
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
Definition: gatherScatter.C:150
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::gSum
Type gSum(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:594
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
OFstream.H
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::OSstream::name
virtual const fileName & name() const
Return the name of the stream.
Definition: OSstream.H:107
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:121
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::foamVersion::version
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
Time.H
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:464
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
ptscotchDecomp.H
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:401
Foam::gMin
Type gMin(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:593
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:303
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Number of processes in parallel run, and 1 for serial run.
Definition: UPstream.H:446