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