backgroundMeshDecomposition.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-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 
30 #include "meshSearch.H"
31 #include "conformationSurfaces.H"
33 #include "Time.H"
34 #include "Random.H"
35 #include "pointConversion.H"
36 #include "decompositionModel.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(backgroundMeshDecomposition, 0);
43 }
44 
45 
46 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
47 
49 (
50  const List<label>& toProc
51 )
52 {
53  // Determine send map
54  // ~~~~~~~~~~~~~~~~~~
55 
56  // 1. Count
57  labelList nSend(Pstream::nProcs(), Zero);
58 
59  forAll(toProc, i)
60  {
61  label proci = toProc[i];
62 
63  nSend[proci]++;
64  }
65 
66 
67  // 2. Size sendMap
68  labelListList sendMap(Pstream::nProcs());
69 
70  forAll(nSend, proci)
71  {
72  sendMap[proci].setSize(nSend[proci]);
73 
74  nSend[proci] = 0;
75  }
76 
77  // 3. Fill sendMap
78  forAll(toProc, i)
79  {
80  label proci = toProc[i];
81 
82  sendMap[proci][nSend[proci]++] = i;
83  }
84 
85  // 4. Send over how many I need to receive
86  labelList recvSizes;
87  Pstream::exchangeSizes(sendMap, recvSizes);
88 
89 
90  // Determine receive map
91  // ~~~~~~~~~~~~~~~~~~~~~
92 
93  labelListList constructMap(Pstream::nProcs());
94 
95  // Local transfers first
96  constructMap[Pstream::myProcNo()] = identity
97  (
98  sendMap[Pstream::myProcNo()].size()
99  );
100 
101  label constructSize = constructMap[Pstream::myProcNo()].size();
102 
103  forAll(constructMap, proci)
104  {
105  if (proci != Pstream::myProcNo())
106  {
107  label nRecv = recvSizes[proci];
108 
109  constructMap[proci].setSize(nRecv);
110 
111  for (label i = 0; i < nRecv; i++)
112  {
113  constructMap[proci][i] = constructSize++;
114  }
115  }
116  }
117 
119  (
120  constructSize,
121  std::move(sendMap),
122  std::move(constructMap)
123  );
124 }
125 
126 
127 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
128 
129 void Foam::backgroundMeshDecomposition::initialRefinement()
130 {
131  volScalarField cellWeights
132  (
133  IOobject
134  (
135  "cellWeights",
136  mesh_.time().timeName(),
137  mesh_,
140  ),
141  mesh_,
142  dimensionedScalar("one", dimless, 1.0),
143  zeroGradientFvPatchScalarField::typeName
144  );
145 
146  const conformationSurfaces& geometry = geometryToConformTo_;
147 
148  decompositionMethod& decomposer =
150 
151  volScalarField::Internal& icellWeights = cellWeights;
152 
153  // For each cell in the mesh has it been determined if it is fully
154  // inside, outside, or overlaps the surface
155  List<volumeType> volumeStatus
156  (
157  mesh_.nCells(),
159  );
160 
161  // Surface refinement
162  {
163  while (true)
164  {
165  // Determine/update the status of each cell
166  forAll(volumeStatus, celli)
167  {
168  if (volumeStatus[celli] == volumeType::UNKNOWN)
169  {
170  treeBoundBox cellBb
171  (
172  mesh_.cells()[celli].points
173  (
174  mesh_.faces(),
175  mesh_.points()
176  )
177  );
178 
179  if (geometry.overlaps(cellBb))
180  {
181  volumeStatus[celli] = volumeType::MIXED;
182  }
183  else if (geometry.inside(cellBb.centre()))
184  {
185  volumeStatus[celli] = volumeType::INSIDE;
186  }
187  else
188  {
189  volumeStatus[celli] = volumeType::OUTSIDE;
190  }
191  }
192  }
193 
194  {
195  labelList refCells = selectRefinementCells
196  (
197  volumeStatus,
198  cellWeights
199  );
200 
201  // Maintain 2:1 ratio
202  labelList newCellsToRefine
203  (
204  meshCutter_.consistentRefinement
205  (
206  refCells,
207  true // extend set
208  )
209  );
210 
211  forAll(newCellsToRefine, nCTRI)
212  {
213  label celli = newCellsToRefine[nCTRI];
214 
215  if (volumeStatus[celli] == volumeType::MIXED)
216  {
217  volumeStatus[celli] = volumeType::UNKNOWN;
218  }
219 
220  icellWeights[celli] = max
221  (
222  1.0,
223  icellWeights[celli]/8.0
224  );
225  }
226 
227  if (returnReduce(newCellsToRefine.size(), sumOp<label>()) == 0)
228  {
229  break;
230  }
231 
232  // Mesh changing engine.
233  polyTopoChange meshMod(mesh_);
234 
235  // Play refinement commands into mesh changer.
236  meshCutter_.setRefinement(newCellsToRefine, meshMod);
237 
238  // Create mesh, return map from old to new mesh.
239  autoPtr<mapPolyMesh> map = meshMod.changeMesh
240  (
241  mesh_,
242  false, // inflate
243  true, // syncParallel
244  true, // orderCells (to reduce cell transfers)
245  false // orderPoints
246  );
247 
248  // Update fields
249  mesh_.updateMesh(map());
250 
251  // Update numbering of cells/vertices.
252  meshCutter_.updateMesh(map());
253 
254  {
255  // Map volumeStatus
256 
257  const labelList& cellMap = map().cellMap();
258 
259  List<volumeType> newVolumeStatus(cellMap.size());
260 
261  forAll(cellMap, newCelli)
262  {
263  label oldCelli = cellMap[newCelli];
264 
265  if (oldCelli == -1)
266  {
267  newVolumeStatus[newCelli] = volumeType::UNKNOWN;
268  }
269  else
270  {
271  newVolumeStatus[newCelli] = volumeStatus[oldCelli];
272  }
273  }
274 
275  volumeStatus.transfer(newVolumeStatus);
276  }
277 
278  Info<< " Background mesh refined from "
279  << returnReduce(map().nOldCells(), sumOp<label>())
280  << " to " << mesh_.globalData().nTotalCells()
281  << " cells." << endl;
282  }
283 
284  // Determine/update the status of each cell
285  forAll(volumeStatus, celli)
286  {
287  if (volumeStatus[celli] == volumeType::UNKNOWN)
288  {
289  treeBoundBox cellBb
290  (
291  mesh_.cells()[celli].points
292  (
293  mesh_.faces(),
294  mesh_.points()
295  )
296  );
297 
298  if (geometry.overlaps(cellBb))
299  {
300  volumeStatus[celli] = volumeType::MIXED;
301  }
302  else if (geometry.inside(cellBb.centre()))
303  {
304  volumeStatus[celli] = volumeType::INSIDE;
305  }
306  else
307  {
308  volumeStatus[celli] = volumeType::OUTSIDE;
309  }
310  }
311  }
312 
313  // Hard code switch for this stage for testing
314  bool removeOutsideCells = false;
315 
316  if (removeOutsideCells)
317  {
318  DynamicList<label> cellsToRemove;
319 
320  forAll(volumeStatus, celli)
321  {
322  if (volumeStatus[celli] == volumeType::OUTSIDE)
323  {
324  cellsToRemove.append(celli);
325  }
326  }
327 
328  removeCells cellRemover(mesh_);
329 
330  // Mesh changing engine.
331  polyTopoChange meshMod(mesh_);
332 
333  labelList exposedFaces = cellRemover.getExposedFaces
334  (
335  cellsToRemove
336  );
337 
338  // Play refinement commands into mesh changer.
339  cellRemover.setRefinement
340  (
341  cellsToRemove,
342  exposedFaces,
343  labelList(exposedFaces.size(), Zero), // patchID dummy
344  meshMod
345  );
346 
347  // Create mesh, return map from old to new mesh.
348  autoPtr<mapPolyMesh> map = meshMod.changeMesh
349  (
350  mesh_,
351  false, // inflate
352  true, // syncParallel
353  true, // orderCells (to reduce cell transfers)
354  false // orderPoints
355  );
356 
357  // Update fields
358  mesh_.updateMesh(map());
359 
360  // Update numbering of cells/vertices.
361  meshCutter_.updateMesh(map());
362  cellRemover.updateMesh(map());
363 
364  {
365  // Map volumeStatus
366 
367  const labelList& cellMap = map().cellMap();
368 
369  List<volumeType> newVolumeStatus(cellMap.size());
370 
371  forAll(cellMap, newCelli)
372  {
373  label oldCelli = cellMap[newCelli];
374 
375  if (oldCelli == -1)
376  {
377  newVolumeStatus[newCelli] = volumeType::UNKNOWN;
378  }
379  else
380  {
381  newVolumeStatus[newCelli] = volumeStatus[oldCelli];
382  }
383  }
384 
385  volumeStatus.transfer(newVolumeStatus);
386  }
387 
388  Info<< "Removed "
389  << returnReduce(map().nOldCells(), sumOp<label>())
390  - mesh_.globalData().nTotalCells()
391  << " cells." << endl;
392  }
393 
394  if (debug)
395  {
396  // const_cast<Time&>(mesh_.time())++;
397  // Info<< "Time " << mesh_.time().timeName() << endl;
398  meshCutter_.write();
399  mesh_.write();
400  cellWeights.write();
401  }
402 
403  labelList newDecomp = decomposer.decompose
404  (
405  mesh_,
406  mesh_.cellCentres(),
407  icellWeights
408  );
409 
410  fvMeshDistribute distributor(mesh_);
411 
412  autoPtr<mapDistributePolyMesh> mapDist = distributor.distribute
413  (
414  newDecomp
415  );
416 
417  meshCutter_.distribute(mapDist());
418 
419  mapDist().distributeCellData(volumeStatus);
420 
421  if (debug)
422  {
423  printMeshData(mesh_);
424 
425  // const_cast<Time&>(mesh_.time())++;
426  // Info<< "Time " << mesh_.time().timeName() << endl;
427  meshCutter_.write();
428  mesh_.write();
429  cellWeights.write();
430  }
431  }
432  }
433 
434  if (debug)
435  {
436  // const_cast<Time&>(mesh_.time())++;
437  // Info<< "Time " << mesh_.time().timeName() << endl;
438  cellWeights.write();
439  mesh_.write();
440  }
441 
442  buildPatchAndTree();
443 }
444 
445 
446 void Foam::backgroundMeshDecomposition::printMeshData
447 (
448  const polyMesh& mesh
449 ) const
450 {
451  // Collect all data on master
452 
453  globalIndex globalCells(mesh.nCells());
454  // labelListList patchNeiProcNo(Pstream::nProcs());
455  // labelListList patchSize(Pstream::nProcs());
456  // const labelList& pPatches = mesh.globalData().processorPatches();
457  // patchNeiProcNo[Pstream::myProcNo()].setSize(pPatches.size());
458  // patchSize[Pstream::myProcNo()].setSize(pPatches.size());
459  // forAll(pPatches, i)
460  // {
461  // const processorPolyPatch& ppp = refCast<const processorPolyPatch>
462  // (
463  // mesh.boundaryMesh()[pPatches[i]]
464  // );
465  // patchNeiProcNo[Pstream::myProcNo()][i] = ppp.neighbProcNo();
466  // patchSize[Pstream::myProcNo()][i] = ppp.size();
467  // }
468  // Pstream::gatherList(patchNeiProcNo);
469  // Pstream::gatherList(patchSize);
470 
471 
472  // // Print stats
473 
474  // globalIndex globalBoundaryFaces(mesh.nBoundaryFaces());
475 
476  for (const int proci : Pstream::allProcs())
477  {
478  Info<< "Processor " << proci << " "
479  << "Number of cells = " << globalCells.localSize(proci)
480  << endl;
481 
482  // label nProcFaces = 0;
483 
484  // const labelList& nei = patchNeiProcNo[proci];
485 
486  // forAll(patchNeiProcNo[proci], i)
487  // {
488  // Info<< " Number of faces shared with processor "
489  // << patchNeiProcNo[proci][i] << " = " << patchSize[proci][i]
490  // << endl;
491 
492  // nProcFaces += patchSize[proci][i];
493  // }
494 
495  // Info<< " Number of processor patches = " << nei.size() << nl
496  // << " Number of processor faces = " << nProcFaces << nl
497  // << " Number of boundary faces = "
498  // << globalBoundaryFaces.localSize(proci) << endl;
499  }
500 }
501 
502 
503 bool Foam::backgroundMeshDecomposition::refineCell
504 (
505  label celli,
506  volumeType volType,
507  scalar& weightEstimate
508 ) const
509 {
510  // Sample the box to find an estimate of the min size, and a volume
511  // estimate when overlapping == true.
512 
513 // const conformationSurfaces& geometry = geometryToConformTo_;
514 
515  treeBoundBox cellBb
516  (
517  mesh_.cells()[celli].points
518  (
519  mesh_.faces(),
520  mesh_.points()
521  )
522  );
523 
524  weightEstimate = 1.0;
525 
526  if (volType == volumeType::MIXED)
527  {
528 // // Assess the cell size at the nearest point on the surface for the
529 // // MIXED cells, if the cell is large with respect to the cell size,
530 // // then refine it.
531 //
532 // pointField samplePoints
533 // (
534 // volRes_*volRes_*volRes_,
535 // Zero
536 // );
537 //
538 // // scalar sampleVol = cellBb.volume()/samplePoints.size();
539 //
540 // vector delta = cellBb.span()/volRes_;
541 //
542 // label pI = 0;
543 //
544 // for (label i = 0; i < volRes_; i++)
545 // {
546 // for (label j = 0; j < volRes_; j++)
547 // {
548 // for (label k = 0; k < volRes_; k++)
549 // {
550 // samplePoints[pI++] =
551 // cellBb.min()
552 // + vector
553 // (
554 // delta.x()*(i + 0.5),
555 // delta.y()*(j + 0.5),
556 // delta.z()*(k + 0.5)
557 // );
558 // }
559 // }
560 // }
561 //
562 // List<pointIndexHit> hitInfo;
563 // labelList hitSurfaces;
564 //
565 // geometry.findSurfaceNearest
566 // (
567 // samplePoints,
568 // scalarField(samplePoints.size(), sqr(GREAT)),
569 // hitInfo,
570 // hitSurfaces
571 // );
572 //
573 // // weightEstimate = 0.0;
574 //
575 // scalar minCellSize = GREAT;
576 //
577 // forAll(samplePoints, i)
578 // {
579 // scalar s = cellShapeControl_.cellSize
580 // (
581 // hitInfo[i].hitPoint()
582 // );
583 //
584 // // Info<< "cellBb.centre() " << cellBb.centre() << nl
585 // // << samplePoints[i] << nl
586 // // << hitInfo[i] << nl
587 // // << "cellBb.span() " << cellBb.span() << nl
588 // // << "cellBb.mag() " << cellBb.mag() << nl
589 // // << s << endl;
590 //
591 // if (s < minCellSize)
592 // {
593 // minCellSize = max(s, minCellSizeLimit_);
594 // }
595 //
596 // // Estimate the number of points in the cell by the surface size,
597 // // this is likely to be too small, so reduce.
598 // // weightEstimate += sampleVol/pow3(s);
599 // }
600 //
601 // if (sqr(spanScale_)*sqr(minCellSize) < magSqr(cellBb.span()))
602 // {
603 // return true;
604 // }
605  }
606  else if (volType == volumeType::INSIDE)
607  {
608  // scalar s =
609  // foamyHexMesh_.cellShapeControl_.cellSize(cellBb.centre());
610 
611  // Estimate number of points in cell by the size at the cell centre
612  // weightEstimate = cellBb.volume()/pow3(s);
613 
614  return false;
615  }
616  // else
617  // {
618  // weightEstimate = 1.0;
619 
620  // return false;
621  // }
622 
623  return false;
624 }
625 
626 
627 Foam::labelList Foam::backgroundMeshDecomposition::selectRefinementCells
628 (
629  List<volumeType>& volumeStatus,
630  volScalarField& cellWeights
631 ) const
632 {
633  volScalarField::Internal& icellWeights = cellWeights;
634 
635  labelHashSet cellsToRefine;
636 
637  // Determine/update the status of each cell
638  forAll(volumeStatus, celli)
639  {
640  if (volumeStatus[celli] == volumeType::MIXED)
641  {
642  if (meshCutter_.cellLevel()[celli] < minLevels_)
643  {
644  cellsToRefine.insert(celli);
645  }
646  }
647 
648  if (volumeStatus[celli] != volumeType::OUTSIDE)
649  {
650  if
651  (
652  refineCell
653  (
654  celli,
655  volumeStatus[celli],
656  icellWeights[celli]
657  )
658  )
659  {
660  cellsToRefine.insert(celli);
661  }
662  }
663  }
664 
665  return cellsToRefine.toc();
666 }
667 
668 
669 void Foam::backgroundMeshDecomposition::buildPatchAndTree()
670 {
671  primitivePatch tmpBoundaryFaces
672  (
673  SubList<face>
674  (
675  mesh_.faces(),
676  mesh_.nBoundaryFaces(),
677  mesh_.nInternalFaces()
678  ),
679  mesh_.points()
680  );
681 
682  boundaryFacesPtr_.reset
683  (
684  new bPatch
685  (
686  tmpBoundaryFaces.localFaces(),
687  tmpBoundaryFaces.localPoints()
688  )
689  );
690 
691  // Overall bb
692  treeBoundBox overallBb(boundaryFacesPtr_().localPoints());
693 
694  Random& rnd = rndGen_;
695 
696  bFTreePtr_.reset
697  (
698  new indexedOctree<treeDataBPatch>
699  (
701  (
702  false,
703  boundaryFacesPtr_(),
705  ),
706  overallBb.extend(rnd, 1e-4),
707  10, // maxLevel
708  10, // leafSize
709  3.0 // duplicity
710  )
711  );
712 
713  // Give the bounds of every processor to every other processor
714  allBackgroundMeshBounds_[Pstream::myProcNo()] = overallBb;
715 
716  Pstream::gatherList(allBackgroundMeshBounds_);
717  Pstream::scatterList(allBackgroundMeshBounds_);
718 
719  // find global bounding box
720  globalBackgroundBounds_ = treeBoundBox(boundBox::invertedBox);
721  forAll(allBackgroundMeshBounds_, proci)
722  {
723  globalBackgroundBounds_.add(allBackgroundMeshBounds_[proci]);
724  }
725 
726  if (false)
727  {
728  OFstream fStr
729  (
730  mesh_.time().path()
731  /"backgroundMeshDecomposition_proc_"
733  + "_boundaryFaces.obj"
734  );
735 
736  const faceList& faces = boundaryFacesPtr_().localFaces();
737  const List<point>& points = boundaryFacesPtr_().localPoints();
738 
739  Map<label> foamToObj(points.size());
740 
741  label vertI = 0;
742 
743  forAll(faces, i)
744  {
745  const face& f = faces[i];
746 
747  forAll(f, fPI)
748  {
749  if (foamToObj.insert(f[fPI], vertI))
750  {
751  meshTools::writeOBJ(fStr, points[f[fPI]]);
752  vertI++;
753  }
754  }
755 
756  fStr<< 'f';
757 
758  forAll(f, fPI)
759  {
760  fStr<< ' ' << foamToObj[f[fPI]] + 1;
761  }
762 
763  fStr<< nl;
764  }
765  }
766 }
767 
768 
769 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
770 
771 Foam::backgroundMeshDecomposition::backgroundMeshDecomposition
772 (
773  const Time& runTime,
774  Random& rndGen,
775  const conformationSurfaces& geometryToConformTo,
776  const dictionary& coeffsDict,
777  const fileName& decompDictFile
778 )
779 :
780  runTime_(runTime),
781  geometryToConformTo_(geometryToConformTo),
782  rndGen_(rndGen),
783  mesh_
784  (
785  IOobject
786  (
787  "backgroundMeshDecomposition",
788  runTime_.timeName(),
789  runTime_,
790  IOobject::MUST_READ,
791  IOobject::AUTO_WRITE,
792  false
793  )
794  ),
795  meshCutter_
796  (
797  mesh_,
798  labelList(mesh_.nCells(), Zero),
799  labelList(mesh_.nPoints(), Zero)
800  ),
801  boundaryFacesPtr_(),
802  bFTreePtr_(),
803  allBackgroundMeshBounds_(Pstream::nProcs()),
804  globalBackgroundBounds_(),
805  mergeDist_(1e-6*mesh_.bounds().mag()),
806  spanScale_(coeffsDict.get<scalar>("spanScale")),
807  minCellSizeLimit_
808  (
809  coeffsDict.getOrDefault<scalar>("minCellSizeLimit", 0)
810  ),
811  minLevels_(coeffsDict.get<label>("minLevels")),
812  volRes_(coeffsDict.get<label>("sampleResolution")),
813  maxCellWeightCoeff_(coeffsDict.get<scalar>("maxCellWeightCoeff"))
814 {
815  if (!Pstream::parRun())
816  {
818  << "This cannot be used when not running in parallel."
819  << exit(FatalError);
820  }
821 
822  const decompositionMethod& decomposer =
823  decompositionModel::New(mesh_, decompDictFile).decomposer();
824 
825  if (!decomposer.parallelAware())
826  {
828  << "You have selected decomposition method "
829  << decomposer.typeName
830  << " which is not parallel aware." << endl
831  << exit(FatalError);
832  }
833 
834  Info<< nl << "Building initial background mesh decomposition" << endl;
835 
836  initialRefinement();
837 }
838 
839 
840 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
841 
844 (
845  volScalarField& cellWeights
846 )
847 {
848  if (debug)
849  {
850  // const_cast<Time&>(mesh_.time())++;
851  // Info<< "Time " << mesh_.time().timeName() << endl;
852  cellWeights.write();
853  mesh_.write();
854  }
855 
856  volScalarField::Internal& icellWeights = cellWeights;
857 
858  while (true)
859  {
860  // Refine large cells if necessary
861 
862  label nOccupiedCells = 0;
863 
864  forAll(icellWeights, cI)
865  {
866  if (icellWeights[cI] > 1 - SMALL)
867  {
868  nOccupiedCells++;
869  }
870  }
871 
872  // Only look at occupied cells, as there is a possibility of runaway
873  // refinement if the number of cells grows too fast. Also, clip the
874  // minimum cellWeightLimit at maxCellWeightCoeff_
875 
876  scalar cellWeightLimit = max
877  (
878  maxCellWeightCoeff_
879  *sum(cellWeights).value()
880  /returnReduce(nOccupiedCells, sumOp<label>()),
881  maxCellWeightCoeff_
882  );
883 
884  if (debug)
885  {
886  Info<< " cellWeightLimit " << cellWeightLimit << endl;
887 
888  Pout<< " sum(cellWeights) " << sum(cellWeights.primitiveField())
889  << " max(cellWeights) " << max(cellWeights.primitiveField())
890  << endl;
891  }
892 
893  labelHashSet cellsToRefine;
894 
895  forAll(icellWeights, cWI)
896  {
897  if (icellWeights[cWI] > cellWeightLimit)
898  {
899  cellsToRefine.insert(cWI);
900  }
901  }
902 
903  if (returnReduce(cellsToRefine.size(), sumOp<label>()) == 0)
904  {
905  break;
906  }
907 
908  // Maintain 2:1 ratio
909  labelList newCellsToRefine
910  (
911  meshCutter_.consistentRefinement
912  (
913  cellsToRefine.toc(),
914  true // extend set
915  )
916  );
917 
918  if (debug && !cellsToRefine.empty())
919  {
920  Pout<< " cellWeights too large in " << cellsToRefine.size()
921  << " cells" << endl;
922  }
923 
924  forAll(newCellsToRefine, nCTRI)
925  {
926  label celli = newCellsToRefine[nCTRI];
927 
928  icellWeights[celli] /= 8.0;
929  }
930 
931  // Mesh changing engine.
932  polyTopoChange meshMod(mesh_);
933 
934  // Play refinement commands into mesh changer.
935  meshCutter_.setRefinement(newCellsToRefine, meshMod);
936 
937  // Create mesh, return map from old to new mesh.
938  autoPtr<mapPolyMesh> map = meshMod.changeMesh
939  (
940  mesh_,
941  false, // inflate
942  true, // syncParallel
943  true, // orderCells (to reduce cell motion)
944  false // orderPoints
945  );
946 
947  // Update fields
948  mesh_.updateMesh(map());
949 
950  // Update numbering of cells/vertices.
951  meshCutter_.updateMesh(map());
952 
953  Info<< " Background mesh refined from "
954  << returnReduce(map().nOldCells(), sumOp<label>())
955  << " to " << mesh_.globalData().nTotalCells()
956  << " cells." << endl;
957 
958  if (debug)
959  {
960  // const_cast<Time&>(mesh_.time())++;
961  // Info<< "Time " << mesh_.time().timeName() << endl;
962  cellWeights.write();
963  mesh_.write();
964  }
965  }
966 
967  if (debug)
968  {
969  printMeshData(mesh_);
970 
971  Pout<< " Pre distribute sum(cellWeights) "
972  << sum(icellWeights)
973  << " max(cellWeights) "
974  << max(icellWeights)
975  << endl;
976  }
977 
978  decompositionMethod& decomposer =
980 
981  labelList newDecomp = decomposer.decompose
982  (
983  mesh_,
984  mesh_.cellCentres(),
985  icellWeights
986  );
987 
988  Info<< " Redistributing background mesh cells" << endl;
989 
990  fvMeshDistribute distributor(mesh_);
991 
992  autoPtr<mapDistributePolyMesh> mapDist = distributor.distribute(newDecomp);
993 
994  meshCutter_.distribute(mapDist());
995 
996  if (debug)
997  {
998  printMeshData(mesh_);
999 
1000  Pout<< " Post distribute sum(cellWeights) "
1001  << sum(icellWeights)
1002  << " max(cellWeights) "
1003  << max(icellWeights)
1004  << endl;
1005 
1006  // const_cast<Time&>(mesh_.time())++;
1007  // Info<< "Time " << mesh_.time().timeName() << endl;
1008  mesh_.write();
1009  cellWeights.write();
1010  }
1011 
1012  buildPatchAndTree();
1013 
1014  return mapDist;
1015 }
1016 
1017 
1019 (
1020  const point& pt
1021 ) const
1022 {
1023 // return bFTreePtr_().findAnyOverlap(pt, 0.0);
1024 
1025  return (bFTreePtr_().getVolumeType(pt) == volumeType::INSIDE);
1026 }
1027 
1028 
1030 (
1031  const List<point>& pts
1032 ) const
1033 {
1034  boolList posProc(pts.size(), true);
1035 
1036  forAll(pts, pI)
1037  {
1038  posProc[pI] = positionOnThisProcessor(pts[pI]);
1039  }
1040 
1041  return posProc;
1042 }
1043 
1044 
1046 (
1047  const treeBoundBox& box
1048 ) const
1049 {
1050 // return !procBounds().contains(box);
1051  return !bFTreePtr_().findBox(box).empty();
1052 }
1053 
1054 
1056 (
1057  const point& centre,
1058  const scalar radiusSqr
1059 ) const
1060 {
1061  //return bFTreePtr_().findAnyOverlap(centre, radiusSqr);
1062 
1063  return bFTreePtr_().findNearest(centre, radiusSqr).hit();
1064 }
1065 
1066 
1068 (
1069  const point& start,
1070  const point& end
1071 ) const
1072 {
1073  return bFTreePtr_().findLine(start, end);
1074 }
1075 
1076 
1078 (
1079  const point& start,
1080  const point& end
1081 ) const
1082 {
1083  return bFTreePtr_().findLineAny(start, end);
1084 }
1085 
1086 
1088 (
1089  const List<point>& pts
1090 ) const
1091 {
1092  DynamicList<label> toCandidateProc;
1093  DynamicList<point> testPoints;
1094  labelList ptBlockStart(pts.size(), -1);
1095  labelList ptBlockSize(pts.size(), -1);
1096 
1097  label nTotalCandidates = 0;
1098 
1099  forAll(pts, pI)
1100  {
1101  const point& pt = pts[pI];
1102 
1103  label nCandidates = 0;
1104 
1105  forAll(allBackgroundMeshBounds_, proci)
1106  {
1107  // Candidate points may lie just outside a processor box, increase
1108  // test range by using overlaps rather than contains
1109  if (allBackgroundMeshBounds_[proci].overlaps(pt, sqr(SMALL*100)))
1110  {
1111  toCandidateProc.append(proci);
1112  testPoints.append(pt);
1113 
1114  nCandidates++;
1115  }
1116  }
1117 
1118  ptBlockStart[pI] = nTotalCandidates;
1119  ptBlockSize[pI] = nCandidates;
1120 
1121  nTotalCandidates += nCandidates;
1122  }
1123 
1124  // Needed for reverseDistribute
1125  label preDistributionToCandidateProcSize = toCandidateProc.size();
1126 
1127  autoPtr<mapDistribute> map(buildMap(toCandidateProc));
1128 
1129  map().distribute(testPoints);
1130 
1131  List<scalar> distanceSqrToCandidate(testPoints.size(), sqr(GREAT));
1132 
1133  // Test candidate points on candidate processors
1134  forAll(testPoints, tPI)
1135  {
1136  pointIndexHit info = bFTreePtr_().findNearest
1137  (
1138  testPoints[tPI],
1139  sqr(GREAT)
1140  );
1141 
1142  if (info.hit())
1143  {
1144  distanceSqrToCandidate[tPI] = magSqr
1145  (
1146  testPoints[tPI] - info.hitPoint()
1147  );
1148  }
1149  }
1150 
1151  map().reverseDistribute
1152  (
1153  preDistributionToCandidateProcSize,
1154  distanceSqrToCandidate
1155  );
1156 
1157  labelList ptNearestProc(pts.size(), -1);
1158 
1159  forAll(pts, pI)
1160  {
1161  // Extract the sub list of results for this point
1162 
1163  SubList<scalar> ptNearestProcResults
1164  (
1165  distanceSqrToCandidate,
1166  ptBlockSize[pI],
1167  ptBlockStart[pI]
1168  );
1169 
1170  scalar nearestProcDistSqr = GREAT;
1171 
1172  forAll(ptNearestProcResults, pPRI)
1173  {
1174  if (ptNearestProcResults[pPRI] < nearestProcDistSqr)
1175  {
1176  nearestProcDistSqr = ptNearestProcResults[pPRI];
1177 
1178  ptNearestProc[pI] = toCandidateProc[ptBlockStart[pI] + pPRI];
1179  }
1180  }
1181 
1182  if (debug)
1183  {
1184  Pout<< pts[pI] << " nearestProcDistSqr " << nearestProcDistSqr
1185  << " ptNearestProc[pI] " << ptNearestProc[pI] << endl;
1186  }
1187 
1188  if (ptNearestProc[pI] < 0)
1189  {
1191  << "The position " << pts[pI]
1192  << " did not find a nearest point on the background mesh."
1193  << exit(FatalError);
1194  }
1195  }
1196 
1197  return ptNearestProc;
1198 }
1199 
1200 
1201 
1204 (
1205  const List<point>& starts,
1206  const List<point>& ends,
1207  bool includeOwnProcessor
1208 ) const
1209 {
1210  DynamicList<label> toCandidateProc;
1211  DynamicList<point> testStarts;
1212  DynamicList<point> testEnds;
1213  labelList segmentBlockStart(starts.size(), -1);
1214  labelList segmentBlockSize(starts.size(), -1);
1215 
1216  label nTotalCandidates = 0;
1217 
1218  forAll(starts, sI)
1219  {
1220  const point& s = starts[sI];
1221  const point& e = ends[sI];
1222 
1223  // Dummy point for treeBoundBox::intersects
1224  point p(Zero);
1225 
1226  label nCandidates = 0;
1227 
1228  forAll(allBackgroundMeshBounds_, proci)
1229  {
1230  // It is assumed that the sphere in question overlaps the source
1231  // processor, so don't test it, unless includeOwnProcessor is true
1232  if
1233  (
1234  (includeOwnProcessor || proci != Pstream::myProcNo())
1235  && allBackgroundMeshBounds_[proci].intersects(s, e, p)
1236  )
1237  {
1238  toCandidateProc.append(proci);
1239  testStarts.append(s);
1240  testEnds.append(e);
1241 
1242  nCandidates++;
1243  }
1244  }
1245 
1246  segmentBlockStart[sI] = nTotalCandidates;
1247  segmentBlockSize[sI] = nCandidates;
1248 
1249  nTotalCandidates += nCandidates;
1250  }
1251 
1252  // Needed for reverseDistribute
1253  label preDistributionToCandidateProcSize = toCandidateProc.size();
1254 
1255  autoPtr<mapDistribute> map(buildMap(toCandidateProc));
1256 
1257  map().distribute(testStarts);
1258  map().distribute(testEnds);
1259 
1260  List<pointIndexHit> segmentIntersectsCandidate(testStarts.size());
1261 
1262  // Test candidate segments on candidate processors
1263  forAll(testStarts, sI)
1264  {
1265  const point& s = testStarts[sI];
1266  const point& e = testEnds[sI];
1267 
1268  // If the sphere finds some elements of the patch, then it overlaps
1269  segmentIntersectsCandidate[sI] = bFTreePtr_().findLine(s, e);
1270  }
1271 
1272  map().reverseDistribute
1273  (
1274  preDistributionToCandidateProcSize,
1275  segmentIntersectsCandidate
1276  );
1277 
1278  List<List<pointIndexHit>> segmentHitProcs(starts.size());
1279 
1280  // Working storage for assessing processors
1281  DynamicList<pointIndexHit> tmpProcHits;
1282 
1283  forAll(starts, sI)
1284  {
1285  tmpProcHits.clear();
1286 
1287  // Extract the sub list of results for this point
1288 
1289  SubList<pointIndexHit> segmentProcResults
1290  (
1291  segmentIntersectsCandidate,
1292  segmentBlockSize[sI],
1293  segmentBlockStart[sI]
1294  );
1295 
1296  forAll(segmentProcResults, sPRI)
1297  {
1298  if (segmentProcResults[sPRI].hit())
1299  {
1300  tmpProcHits.append(segmentProcResults[sPRI]);
1301 
1302  tmpProcHits.last().setIndex
1303  (
1304  toCandidateProc[segmentBlockStart[sI] + sPRI]
1305  );
1306  }
1307  }
1308 
1309  segmentHitProcs[sI] = tmpProcHits;
1310  }
1311 
1312  return segmentHitProcs;
1313 }
1314 
1315 
1317 (
1318  const point& centre,
1319  const scalar& radiusSqr
1320 ) const
1321 {
1322  forAll(allBackgroundMeshBounds_, proci)
1323  {
1324  if (bFTreePtr_().findNearest(centre, radiusSqr).hit())
1325  {
1326  return true;
1327  }
1328  }
1329 
1330  return false;
1331 }
1332 
1333 
1335 (
1336  const point& centre,
1337  const scalar radiusSqr
1338 ) const
1339 {
1340  DynamicList<label> toProc(Pstream::nProcs());
1341 
1342  forAll(allBackgroundMeshBounds_, proci)
1343  {
1344  // Test against the bounding box of the processor
1345  if
1346  (
1347  proci != Pstream::myProcNo()
1348  && allBackgroundMeshBounds_[proci].overlaps(centre, radiusSqr)
1349  )
1350  {
1351  // Expensive test
1352 // if (bFTreePtr_().findNearest(centre, radiusSqr).hit())
1353  {
1354  toProc.append(proci);
1355  }
1356  }
1357  }
1358 
1359  return toProc;
1360 }
1361 
1362 
1363 //Foam::labelListList Foam::backgroundMeshDecomposition::overlapsProcessors
1364 //(
1365 // const List<point>& centres,
1366 // const List<scalar>& radiusSqrs,
1367 // const Delaunay& T,
1368 // bool includeOwnProcessor
1369 //) const
1370 //{
1371 // DynamicList<label> toCandidateProc;
1372 // DynamicList<point> testCentres;
1373 // DynamicList<scalar> testRadiusSqrs;
1374 // labelList sphereBlockStart(centres.size(), -1);
1375 // labelList sphereBlockSize(centres.size(), -1);
1376 //
1377 // label nTotalCandidates = 0;
1378 //
1379 // forAll(centres, sI)
1380 // {
1381 // const point& c = centres[sI];
1382 // scalar rSqr = radiusSqrs[sI];
1383 //
1384 // label nCandidates = 0;
1385 //
1386 // forAll(allBackgroundMeshBounds_, proci)
1387 // {
1388 // // It is assumed that the sphere in question overlaps the source
1389 // // processor, so don't test it, unless includeOwnProcessor is true
1390 // if
1391 // (
1392 // (includeOwnProcessor || proci != Pstream::myProcNo())
1393 // && allBackgroundMeshBounds_[proci].overlaps(c, rSqr)
1394 // )
1395 // {
1396 // if (bFTreePtr_().findNearest(c, rSqr).hit())
1397 // {
1398 // toCandidateProc.append(proci);
1399 // testCentres.append(c);
1400 // testRadiusSqrs.append(rSqr);
1401 //
1402 // nCandidates++;
1403 // }
1404 // }
1405 // }
1406 //
1407 // sphereBlockStart[sI] = nTotalCandidates;
1408 // sphereBlockSize[sI] = nCandidates;
1409 //
1410 // nTotalCandidates += nCandidates;
1411 // }
1412 //
1413 // // Needed for reverseDistribute
1420 //
1421 // // TODO: This is faster, but results in more vertices being referred
1422 // boolList sphereOverlapsCandidate(testCentres.size(), true);
1459 //
1465 //
1466 // labelListList sphereProcs(centres.size());
1467 //
1468 // // Working storage for assessing processors
1469 // DynamicList<label> tmpProcs;
1470 //
1471 // forAll(centres, sI)
1472 // {
1473 // tmpProcs.clear();
1474 //
1475 // // Extract the sub list of results for this point
1476 //
1477 // SubList<bool> sphereProcResults
1478 // (
1479 // sphereOverlapsCandidate,
1480 // sphereBlockSize[sI],
1481 // sphereBlockStart[sI]
1482 // );
1483 //
1484 // forAll(sphereProcResults, sPRI)
1485 // {
1486 // if (sphereProcResults[sPRI])
1487 // {
1488 // tmpProcs.append(toCandidateProc[sphereBlockStart[sI] + sPRI]);
1489 // }
1490 // }
1491 //
1492 // sphereProcs[sI] = tmpProcs;
1493 // }
1494 //
1495 // return sphereProcs;
1496 //}
1497 
1498 
1499 //Foam::labelListList Foam::backgroundMeshDecomposition::overlapProcessors
1500 //(
1501 // const point& cc,
1502 // const scalar rSqr
1503 //) const
1504 //{
1505 // DynamicList<label> toCandidateProc;
1506 // label sphereBlockStart(-1);
1507 // label sphereBlockSize(-1);
1508 //
1509 // label nCandidates = 0;
1510 //
1511 // forAll(allBackgroundMeshBounds_, proci)
1512 // {
1513 // // It is assumed that the sphere in question overlaps the source
1514 // // processor, so don't test it, unless includeOwnProcessor is true
1515 // if
1516 // (
1517 // (includeOwnProcessor || proci != Pstream::myProcNo())
1518 // && allBackgroundMeshBounds_[proci].overlaps(cc, rSqr)
1519 // )
1520 // {
1521 // toCandidateProc.append(proci);
1522 //
1523 // nCandidates++;
1524 // }
1525 // }
1526 //
1527 // sphereBlockSize = nCandidates;
1528 // nTotalCandidates += nCandidates;
1529 //
1530 // // Needed for reverseDistribute
1531 // label preDistributionToCandidateProcSize = toCandidateProc.size();
1532 //
1533 // autoPtr<mapDistribute> map(buildMap(toCandidateProc));
1534 //
1535 // map().distribute(testCentres);
1536 // map().distribute(testRadiusSqrs);
1537 //
1538 // // TODO: This is faster, but results in more vertices being referred
1540 // boolList sphereOverlapsCandidate(testCentres.size(), false);
1541 //
1542 // // Test candidate spheres on candidate processors
1543 // forAll(testCentres, sI)
1544 // {
1545 // const point& c = testCentres[sI];
1546 // const scalar rSqr = testRadiusSqrs[sI];
1547 //
1548 // const bool flagOverlap = bFTreePtr_().findNearest(c, rSqr).hit();
1549 //
1550 // if (flagOverlap)
1551 // {
1552 // //if (vertexOctree.findAnyOverlap(c, rSqr))
1557 //
1572 // sphereOverlapsCandidate[sI] = true;
1574 // }
1575 // }
1576 //
1577 // map().reverseDistribute
1578 // (
1579 // preDistributionToCandidateProcSize,
1580 // sphereOverlapsCandidate
1581 // );
1582 //
1583 // labelListList sphereProcs(centres.size());
1584 //
1585 // // Working storage for assessing processors
1586 // DynamicList<label> tmpProcs;
1587 //
1588 // forAll(centres, sI)
1589 // {
1590 // tmpProcs.clear();
1591 //
1592 // // Extract the sub list of results for this point
1593 //
1594 // SubList<bool> sphereProcResults
1595 // (
1596 // sphereOverlapsCandidate,
1597 // sphereBlockSize[sI],
1598 // sphereBlockStart[sI]
1599 // );
1600 //
1601 // forAll(sphereProcResults, sPRI)
1602 // {
1603 // if (sphereProcResults[sPRI])
1604 // {
1605 // tmpProcs.append(toCandidateProc[sphereBlockStart[sI] + sPRI]);
1606 // }
1607 // }
1608 //
1609 // sphereProcs[sI] = tmpProcs;
1610 // }
1611 //
1612 // return sphereProcs;
1613 //}
1614 
1615 
1616 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
runTime
engineTime & runTime
Definition: createEngineTime.H:13
p
volScalarField & p
Definition: createFieldRefs.H:8
pointConversion.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
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:203
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Definition: gatherScatterList.C:215
Foam::boundBox::invertedBox
static const boundBox invertedBox
A large inverted boundBox: min/max == +/- ROOTVGREAT.
Definition: boundBox.H:86
Foam::backgroundMeshDecomposition::intersectsProcessors
List< List< pointIndexHit > > intersectsProcessors(const List< point > &starts, const List< point > &ends, bool includeOwnProcessor=false) const
Which processors are intersected by the line segment, returns all.
Foam::Pstream::exchangeSizes
static void exchangeSizes(const Container &sendData, labelList &sizes, const label comm=UPstream::worldComm)
Helper: exchange sizes of sendData. sendData is the data per.
Definition: exchange.C:349
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::decompositionModel::decomposer
decompositionMethod & decomposer() const
Return demand-driven decomposition method.
Definition: decompositionModel.C:101
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
Foam::indexedOctree::perturbTol
static scalar & perturbTol()
Get the perturbation tolerance.
Definition: indexedOctree.C:2383
Foam::decompositionModel::New
static const decompositionModel & New(const polyMesh &mesh, const fileName &decompDictFile="", const dictionary *fallback=nullptr)
Definition: decompositionModel.C:83
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::backgroundMeshDecomposition::findLineAny
pointIndexHit findLineAny(const point &start, const point &end) const
Find any intersection of line between start and end, (exposing.
Foam::primitiveMesh::nCells
label nCells() const noexcept
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::PointIndexHit
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:52
backgroundMeshDecomposition.H
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::GeometricField< scalar, fvPatchField, volMesh >::Internal
DimensionedField< scalar, volMesh > Internal
Type of the internal field from which this GeometricField is derived.
Definition: GeometricField.H:107
Foam::volumeType::UNKNOWN
Unknown state.
Definition: volumeType.H:67
Foam::volumeType::MIXED
A location that is partly inside and outside.
Definition: volumeType.H:70
conformationSurfaces.H
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:42
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
Foam::backgroundMeshDecomposition::overlapsOtherProcessors
bool overlapsOtherProcessors(const point &centre, const scalar &radiusSqr) const
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
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::backgroundMeshDecomposition::processorNearestPosition
labelList processorNearestPosition(const List< point > &pts) const
What is the nearest processor to the given position?
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:121
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::backgroundMeshDecomposition::buildMap
static autoPtr< mapDistribute > buildMap(const List< label > &toProc)
Build a mapDistribute for the supplied destination processor data.
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::backgroundMeshDecomposition::overlapProcessors
labelList overlapProcessors(const point &centre, const scalar radiusSqr) const
Random.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Time.H
Foam::autoPtr< Foam::mapDistribute >
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:453
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::UPstream::allProcs
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:508
Foam::bPatch
PrimitivePatch<::Foam::List< face >, const pointField > bPatch
Definition: backgroundMeshDecomposition.H:83
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
A PointIndexHit for 3D points.
Definition: pointIndexHit.H:46
meshSearch.H
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:463
Foam::nl
constexpr char nl
Definition: Ostream.H:404
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::backgroundMeshDecomposition::findLine
pointIndexHit findLine(const point &start, const point &end) const
Find nearest intersection of line between start and end, (exposing.
Foam::treeDataBPatch
treeDataPrimitivePatch< bPatch > treeDataBPatch
Definition: backgroundMeshDecomposition.H:84
Foam::UPstream::parRun
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
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::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
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::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::backgroundMeshDecomposition::distribute
autoPtr< mapDistributePolyMesh > distribute(volScalarField &cellWeights)
Redistribute the background mesh based on a supplied weight field,.
Foam::volumeType::INSIDE
A location inside the volume.
Definition: volumeType.H:68
Foam::PtrListOps::get
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
rndGen
Random rndGen
Definition: createFields.H:23
Foam::primitivePatch
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
Definition: primitivePatch.H:51
decompositionModel.H
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
zeroGradientFvPatchFields.H
Foam::backgroundMeshDecomposition::overlapsThisProcessor
bool overlapsThisProcessor(const treeBoundBox &box) const
Does the given box overlap the faces of the boundary of this.
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Number of processes in parallel run, and 1 for serial run.
Definition: UPstream.H:445
Foam::volumeType::OUTSIDE
A location outside the volume.
Definition: volumeType.H:69
Foam::dimless
const dimensionSet dimless
Dimensionless.
Definition: dimensionSets.C:189
Foam::backgroundMeshDecomposition::positionOnThisProcessor
bool positionOnThisProcessor(const point &pt) const
Is the given position inside the domain of this decomposition.