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