box.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) 2017-2021 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "box.H"
29 #include "mapDistribute.H"
30 #include "OFstream.H"
31 #include "meshTools.H"
32 
33 const Foam::label Foam::processorLODs::box::DROP = 0;
34 const Foam::label Foam::processorLODs::box::REFINE = 1;
35 const Foam::label Foam::processorLODs::box::FIXED = 2;
36 const Foam::label Foam::processorLODs::box::nStartUpIter = 2;
37 
38 namespace Foam
39 {
40 namespace processorLODs
41 {
43 }
44 }
45 
46 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
47 
49 (
50  const List<DynamicList<treeBoundBox>>& fixedBoxes,
51  const label iter
52 ) const
53 {
54  static label time = 0;
55 
56  OFstream os
57  (
58  "processor" + Foam::name(Pstream::myProcNo())
59  + "_time" + Foam::name(time)
60  + "_iter" + Foam::name(iter) + ".obj"
61  );
62 
63  label verti = 0;
64  for (const int proci : Pstream::allProcs())
65  {
66  if (proci == Pstream::myProcNo())
67  {
68  continue;
69  }
70 
71  const DynamicList<treeBoundBox>& procBoxes = fixedBoxes[proci];
72  forAll(procBoxes, boxi)
73  {
74  const treeBoundBox& bb = procBoxes[boxi];
75 
76  // Write the points
77  const pointField pts(bb.points());
78  for (const point& p : pts)
79  {
81  }
82 
83  // Write the box faces
84  for (const face& f : bb.faces)
85  {
86  os << 'f';
87  for (const label fpi : f)
88  {
89  os << ' ' << fpi + verti + 1;
90  }
91  os << nl;
92  }
93  verti += pts.size();
94  }
95  }
96 
97  ++time;
98 }
99 
100 
102 (
103  const label refineIter,
104  const label nTgtObjects,
105  List<labelHashSet>& fixedSendElems,
106  List<List<labelList>>& localTgtElems,
107  List<labelList>& refineFlags,
108  labelList& nElems
109 ) const
110 {
111  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
112 
113  // Identify src boxes that can be refined and send to all remote procs
114  for (const int proci : Pstream::allProcs())
115  {
116  if (proci != Pstream::myProcNo())
117  {
118  UOPstream toProc(proci, pBufs);
119  toProc << nObjectsOfType_ << boxes_[proci] << newToOld_[proci];
120  }
121  }
122 
123  pBufs.finishedSends();
124 
125  // Test each remote src bb with local tgt objects to identify which remote
126  // src boxes can/should be refined
127  for (const int proci : Pstream::allProcs())
128  {
129  if (proci == Pstream::myProcNo())
130  {
131  // Not refining boxes I send to myself - will be sending all local
132  // elements
133  continue;
134  }
135 
136  // Receive the subset of changing src bound boxes for proci
137  UIPstream fromProc(proci, pBufs);
138  const label nObjects = readLabel(fromProc);
139  List<treeBoundBox> remoteSrcBoxes(fromProc);
140  const List<label> newToOld(fromProc);
141 
142  if (remoteSrcBoxes.empty())
143  {
144  continue;
145  }
146 
147 
148  labelList& procRefineFlags = refineFlags[proci];
149  procRefineFlags.setSize(remoteSrcBoxes.size(), FIXED);
150 
151  if (scalar(nTgtObjects)/scalar(nObjects) < 0.1)
152  {
153  // Sending less than 10% of objects of this type
154  // - shortcut by sending all
155  fixedSendElems[proci].insert(identity(nTgtObjects));
156  nElems[proci] = nTgtObjects;
157 
158  continue;
159  }
160 
161  label nElem = 0;
162  List<labelList>& localProcTgtElems = localTgtElems[proci];
163  List<labelList> newLocalProcTgtElems(remoteSrcBoxes.size());
164 
165  forAll(remoteSrcBoxes, srcBoxi)
166  {
167  const treeBoundBox& remSrcBb = remoteSrcBoxes[srcBoxi];
168  DynamicList<label> selectedElems(maxObjectsPerLeaf_);
169 
170  if (refineIter > nStartUpIter)
171  {
172  // Iterate over cached subset of tgt elements
173  const label oldBoxi = newToOld[srcBoxi];
174  const labelList& tgtBoxElems = localProcTgtElems[oldBoxi];
175 
176  for (const label tgtObji : tgtBoxElems)
177  {
178  if (calcTgtBox(tgtObji).overlaps(remSrcBb))
179  {
180  selectedElems.append(tgtObji);
181  }
182  }
183  }
184  else
185  {
186  // Iterating over all target elements
187  for (label tgtObji = 0; tgtObji < nTgtObjects; ++tgtObji)
188  {
189  if (calcTgtBox(tgtObji).overlaps(remSrcBb))
190  {
191  selectedElems.append(tgtObji);
192  }
193  }
194  }
195 
196  nElem += selectedElems.size();
197 
198  if
199  (
200  proci == Pstream::myProcNo()
201  || selectedElems.size() < maxObjectsPerLeaf_
202  )
203  {
204  procRefineFlags[srcBoxi] = FIXED;
205  fixedSendElems[proci].insert(selectedElems);
206  }
207  else
208  {
209  procRefineFlags[srcBoxi] = REFINE;
210  if (refineIter >= nStartUpIter)
211  {
212  newLocalProcTgtElems[srcBoxi].transfer(selectedElems);
213  }
214  }
215  }
216 
217  localProcTgtElems.transfer(newLocalProcTgtElems);
218  nElems[proci] = nElem;
219  }
220 }
221 
222 
224 (
225  const label boxi,
226  const label refineIter,
227  const label nSrcElem,
228  const treeBoundBox& origBox,
229  DynamicList<treeBoundBox>& procBoxes,
230  DynamicList<labelList>& procBoxElems,
231  DynamicList<label>& procNewToOld
232 ) const
233 {
234  // Create the new boxes
235 
236  if (refineIter == nStartUpIter)
237  {
238  // Start caching the addressing
239  for (direction octant = 0; octant < 8; ++octant)
240  {
241  const treeBoundBox subBb(origBox.subBbox(octant));
242 
243  // Identify the src elements for each box
244  DynamicList<label> newElems(nSrcElem/2);
245 
246  for (label srcElemi = 0; srcElemi < nSrcElem; ++srcElemi)
247  {
248  if (subBb.overlaps(calcSrcBox(srcElemi)))
249  {
250  newElems.append(srcElemi);
251  }
252  }
253 
254  if (newElems.size())
255  {
256  procBoxes.append(subBb);
257  procBoxElems.append(newElems);
258  procNewToOld.append(boxi);
259  }
260  }
261  }
262  else
263  {
264  for (direction octant = 0; octant < 8; ++octant)
265  {
266  const treeBoundBox subBb(origBox.subBbox(octant));
267 
268  for (label srcElemi = 0; srcElemi < nSrcElem; ++srcElemi)
269  {
270  if (subBb.overlaps(calcSrcBox(srcElemi)))
271  {
272  procBoxes.append(subBb);
273  break;
274  }
275  }
276  }
277  }
278 }
279 
280 
282 (
283  const label boxi,
284  const labelList& srcAddr,
285  const treeBoundBox& origBox,
286  DynamicList<treeBoundBox>& procBoxes,
287  DynamicList<labelList>& procBoxElems,
288  DynamicList<label>& procNewToOld
289 ) const
290 {
291  // Create the new boxes
292  for (direction octant = 0; octant < 8; ++octant)
293  {
294  const treeBoundBox subBb(origBox.subBbox(octant));
295 
296  // Identify the src elements for each box
297  DynamicList<label> newElems(srcAddr.size()/2);
298 
299  for (const label srcElemi : srcAddr)
300  {
301  if (subBb.overlaps(calcSrcBox(srcElemi)))
302  {
303  newElems.append(srcElemi);
304  }
305  }
306 
307  // Only keeping new box if it overlaps src objects
308  if (newElems.size())
309  {
310  procBoxes.append(subBb);
311  procBoxElems.append(newElems);
312  procNewToOld.append(boxi);
313  }
314  }
315 }
316 
317 
319 (
320  const label refineIter,
321  const label nSrcFaces,
322  const List<labelList>& refineFlags,
323  List<DynamicList<treeBoundBox>>& fixedBoxes
324 )
325 {
326  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
327 
328  // Send refine info back for list of evolving src boxes
329  forAll(refineFlags, proci)
330  {
331  if (proci != Pstream::myProcNo())
332  {
333  UOPstream toProc(proci, pBufs);
334  toProc << refineFlags[proci];
335  }
336  }
337 
338  pBufs.finishedSends();
339 
340  // Receive refine refinement actions from remote procs and use to refine
341  // local src boxes
342  bool refineBoxes = false;
343  List<DynamicList<label>> newToOld(Pstream::nProcs());
344 
345 
346  for (const int proci : Pstream::allProcs())
347  {
348  if (proci == Pstream::myProcNo())
349  {
350  continue;
351  }
352 
353  UIPstream fromProc(proci, pBufs);
354  const labelList refineFlags(fromProc);
355 
356  const List<treeBoundBox>& procBoxes = boxes_[proci];
357  DynamicList<treeBoundBox> newProcBoxes(procBoxes.size());
358  DynamicList<labelList> newProcBoxElems(procBoxes.size());
359  newToOld[proci].setCapacity(boxes_[proci].size());
360  DynamicList<label>& newProcNewToOld = newToOld[proci];
361 
362 
363  forAll(procBoxes, boxi)
364  {
365  if (refineFlags[boxi] == DROP)
366  {
367  // Skip box
368  }
369  else if (refineFlags[boxi] == REFINE)
370  {
371  if (refineIter > nStartUpIter)
372  {
373  // Can use locally cached info to speed up intersection
374  // tests
375  refineBox
376  (
377  boxi,
378  boxSrcElems_[proci][boxi],
379  procBoxes[boxi],
380  newProcBoxes,
381  newProcBoxElems,
382  newProcNewToOld
383  );
384  }
385  else
386  {
387  refineBox
388  (
389  boxi,
390  refineIter,
391  nSrcFaces,
392  procBoxes[boxi],
393  newProcBoxes,
394  newProcBoxElems,
395  newProcNewToOld
396  );
397  }
398 
399  refineBoxes = true;
400  }
401  else if (refineFlags[boxi] == FIXED)
402  {
403  fixedBoxes[proci].append(procBoxes[boxi]);
404  }
405  else
406  {
408  << "Unhandled refine action " << refineFlags[boxi]
409  << abort(FatalError);
410  }
411  }
412 
413  // Only keeping boxes that are to be refined
414  boxes_[proci].transfer(newProcBoxes);
415  boxSrcElems_[proci].transfer(newProcBoxElems);
416  newToOld_[proci].transfer(newProcNewToOld);
417  }
418 
419  return returnReduce(refineBoxes, orOp<bool>());
420 }
421 
422 
424 (
425  const label nSrcElems,
426  const label nTgtElems
427 )
428 {
429  // Store elements to send - will be used to build the mapDistribute
430  List<labelHashSet> fixedSendElems(Pstream::nProcs());
431 
432  // List of local tgt elems to optimise searching for tgt elements inside
433  // remote src boxes
434  List<List<labelList>> localTgtElems(Pstream::nProcs());
435 
436  // Storage of boxes per processor - only useful for debugging
437  List<DynamicList<treeBoundBox>> fixedBoxes(Pstream::nProcs());
438 
439  // Iterate to subdivide src boxes
440  label refinementIter = 1;
441  bool refineSrcBoxes = true;
442  while (refineSrcBoxes && (refinementIter <= nRefineIterMax_))
443  {
444  // Per processor refinement info
445  List<labelList> refineFlags(Pstream::nProcs());
446  labelList nElems(Pstream::nProcs(), Zero);
447 
448  // Assess how many target elements intersect the source bounding boxes
449  // and use the info to flag how the source boxes should be refined
450  setRefineFlags
451  (
452  refinementIter,
453  nTgtElems,
454  fixedSendElems,
455  localTgtElems,
456  refineFlags,
457  nElems
458  );
459 
460  // Refine the source bounding boxes
461  refineSrcBoxes =
462  doRefineBoxes
463  (
464  refinementIter,
465  nSrcElems,
466  refineFlags,
467  fixedBoxes
468  );
469 
470  ++refinementIter;
471 
472  if (debug > 1)
473  {
474  // Include any boxes that are still evolving
475  List<DynamicList<treeBoundBox>> allBoxes(fixedBoxes);
476  forAll(allBoxes, proci)
477  {
478  allBoxes[proci].append(boxes_[proci]);
479  }
480  writeBoxes(allBoxes, refinementIter);
481  }
482  }
483 
484  if (debug)
485  {
486  Pout<< "Local src boxes after " << refinementIter-1 << " iterations:"
487  << nl;
488 
489  forAll(fixedBoxes, proci)
490  {
491  // Include any boxes that are still evolving in box count
492  label nBox = fixedBoxes[proci].size() + boxes_[proci].size();
493  Pout<< " proc:" << proci << " nBoxes:" << nBox << nl;
494  }
495  Pout<< endl;
496  }
497 
498  // Convert send elems into a List<labelList>
499  List<labelList> sendElems(Pstream::nProcs());
500  forAll(localTgtElems, proci)
501  {
502  if (proci == Pstream::myProcNo() && nSrcElems)
503  {
504  sendElems[proci] = identity(nTgtElems);
505  }
506  else
507  {
508  labelHashSet& allIDs = fixedSendElems[proci];
509 
510  const List<labelList>& procBoxElems = localTgtElems[proci];
511 
512  for (const labelList& elems: procBoxElems)
513  {
514  allIDs.insert(elems);
515  }
516 
517  sendElems[proci] = allIDs.toc();
518  }
519  }
520 
521  fixedSendElems.clear();
522  localTgtElems.clear();
523 
524  if (debug)
525  {
526  Pout<< "Local objects: " << nTgtElems << " Send map:" << nl
527  << tab << "proc" << tab << "objects" << endl;
528 
529  forAll(sendElems, proci)
530  {
531  Pout<< tab << proci << tab << sendElems[proci].size()
532  << endl;
533  }
534  }
535 
536  return createLODMap(sendElems);
537 }
538 
539 
541 (
542  List<labelList>& sendElems
543 ) const
544 {
545  // Send over how many objects I need to receive
546  const label localProci = Pstream::myProcNo();
547  labelListList sendSizes(Pstream::nProcs());
548  sendSizes[localProci].setSize(Pstream::nProcs());
549  forAll(sendElems, proci)
550  {
551  sendSizes[localProci][proci] = sendElems[proci].size();
552  }
553  Pstream::gatherList(sendSizes);
554  Pstream::scatterList(sendSizes);
555 
556 
557  // Determine order of receiving
558  labelListList constructMap(Pstream::nProcs());
559 
560  // My local segment first
561  constructMap[localProci] = identity(sendElems[localProci].size());
562 
563  label segmenti = constructMap[localProci].size();
564  forAll(constructMap, proci)
565  {
566  if (proci != localProci)
567  {
568  // What I need to receive is what other processor is sending to me
569  label nRecv = sendSizes[proci][localProci];
570  constructMap[proci].setSize(nRecv);
571 
572  for (label& addr : constructMap[proci])
573  {
574  addr = segmenti++;
575  }
576  }
577  }
578 
580  (
581  new mapDistribute
582  (
583  segmenti, // size after construction
584  std::move(sendElems),
585  std::move(constructMap)
586  )
587  );
588 
589  return mapPtr;
590 }
591 
592 
593 // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
594 
596 (
597  const UList<point>& srcPoints,
598  const UList<point>& tgtPoints,
599  const label maxObjectsPerLeaf,
600  const label nObjectsOfType,
601  const label nRefineIterMax
602 )
603 :
604  processorLOD(maxObjectsPerLeaf, nObjectsOfType),
605  srcPoints_(srcPoints),
606  tgtPoints_(tgtPoints),
607  boxes_(Pstream::nProcs()),
608  nRefineIterMax_(nRefineIterMax),
609  newToOld_(Pstream::nProcs()),
610  boxSrcElems_(Pstream::nProcs())
611 {
612  // Initialise each processor with a single box large enough to include all
613  // of its local src points
614  if (srcPoints_.size())
615  {
616  forAll(boxes_, proci)
617  {
618  List<treeBoundBox>& procBoxes = boxes_[proci];
619 
620  // Note: inflate to ease overlap operations and to handle 2-D
621  // axis-aligned objects
622  treeBoundBox srcBb(srcPoints_);
623  srcBb.inflate(0.01);
624 
625  DynamicList<treeBoundBox> newProcBoxes(1);
626  newProcBoxes.append(srcBb);
627  procBoxes.transfer(newProcBoxes);
628  }
629  }
630 }
631 
632 
633 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
meshTools.H
Foam::processorLODs::box::box
box(const UList< point > &srcPoints, const UList< point > &tgtPoints, const label maxObjectsPerLeaf, const label nObjectsOfType, const label nRefineIterMax=100)
Construct from list of points.
Definition: box.C:596
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::UOPstream
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:57
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::processorLODs::box::nStartUpIter
static const label nStartUpIter
Number of iterations before element indices are cached.
Definition: box.H:96
Foam::treeBoundBox::points
tmp< pointField > points() const
Vertex coordinates. In octant coding.
Definition: treeBoundBox.C:92
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:55
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:203
Foam::boundBox::inflate
void inflate(const scalar s)
Inflate box by factor*mag(span) in all dimensions.
Definition: boundBox.C:175
Foam::treeBoundBox
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:86
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:88
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::processorLODs::box::setRefineFlags
void setRefineFlags(const label refineIter, const label nTgtObjects, List< labelHashSet > &fixedSendElems, List< List< labelList >> &localTgtElems, List< labelList > &refineFlags, labelList &nElems) const
Set the box refinement flags.
Definition: box.C:102
Foam::processorLODs::box::DROP
static const label DROP
Drop/discard.
Definition: box.H:70
Foam::processorLODs::box::FIXED
static const label FIXED
Fixed - do not touch.
Definition: box.H:76
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::processorLODs::box::refineBox
void refineBox(const label boxi, const label refineIter, const label nSrcElem, const treeBoundBox &origBox, DynamicList< treeBoundBox > &procBoxes, DynamicList< labelList > &procBoxElems, DynamicList< label > &procNewToOld) const
Definition: box.C:224
Foam::HashSet< label, Hash< label > >
Foam::treeBoundBox::subBbox
treeBoundBox subBbox(const direction octant) const
Sub-box of given octant. Midpoint calculated.
Definition: treeBoundBox.C:106
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
OFstream.H
Foam::processorLODs::box
Creates the parallel distribution map by describing the source and target objects using box shapes.
Definition: box.H:59
Foam::Field< vector >
Foam::treeBoundBox::faces
static const faceList faces
Face to point addressing.
Definition: treeBoundBox.H:151
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:163
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:456
Foam::processorLODs::box::createMap
autoPtr< mapDistribute > createMap(const label nSrcElems, const label nTgtElems)
Definition: box.C:424
box.H
Foam::PstreamBuffers::finishedSends
void finishedSends(const bool block=true)
Mark all sends as having been done.
Definition: PstreamBuffers.C:73
Foam::processorLODs::defineTypeNameAndDebug
defineTypeNameAndDebug(box, 0)
Foam::processorLOD
Base class to generate a parallel distribution map for sending sufficient target objects to cover a d...
Definition: processorLOD.H:52
Foam::processorLODs::box::writeBoxes
void writeBoxes(const List< DynamicList< treeBoundBox >> &fixedBoxes, const label iter) const
Helper function to write the boxes in OBJ format.
Definition: box.C:49
Foam::FatalError
error FatalError
os
OBJstream os(runTime.globalPath()/outputName)
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::autoPtr< Foam::mapDistribute >
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::processorLODs::box::REFINE
static const label REFINE
Refine.
Definition: box.H:73
Foam::tab
constexpr char tab
Definition: Ostream.H:403
Foam::nl
constexpr char nl
Definition: Ostream.H:404
mapDistribute.H
f
labelList f(nPoints)
Foam::Vector< scalar >
Foam::readLabel
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:66
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
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
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
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:116
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
Foam::direction
uint8_t direction
Definition: direction.H:52
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::processorLODs::box::doRefineBoxes
bool doRefineBoxes(const label refineIter, const label nSrcFaces, const List< labelList > &refineFlags, List< DynamicList< treeBoundBox >> &fixedBoxes)
Apply the box refinements.
Definition: box.C:319
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::UIPstream
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:56
Foam::orOp
Definition: ops.H:234
Foam::processorLODs::box::createLODMap
autoPtr< mapDistribute > createLODMap(List< labelList > &sendElems) const
Use the current list of send elements to create the mapDistribute.
Definition: box.C:541