inverseDistanceCellCellStencil.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-2019 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 i
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 
30 #include "OBJstream.H"
31 #include "Time.H"
32 #include "fvMeshSubset.H"
33 
34 #include "globalIndex.H"
35 #include "oversetFvPatch.H"
37 #include "syncTools.H"
38 #include "treeBoundBoxList.H"
39 #include "waveMethod.H"
40 
41 #include "regionSplit.H"
42 #include "dynamicOversetFvMesh.H"
43 //#include "minData.H"
44 //#include "FaceCellWave.H"
45 
46 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
47 
48 namespace Foam
49 {
50 namespace cellCellStencils
51 {
52  defineTypeNameAndDebug(inverseDistance, 0);
53  addToRunTimeSelectionTable(cellCellStencil, inverseDistance, mesh);
54 }
55 }
56 
57 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
58 
60 (
61  const labelVector& nDivs,
62  const labelVector& ijk
63 )
64 {
65  return (ijk[0]*nDivs[1] + ijk[1])*nDivs[2] + ijk[2];
66 }
67 
68 
70 (
71  const labelVector& nDivs,
72  const label boxI
73 )
74 {
75  label ij = boxI/nDivs[2];
76  label k = boxI-ij*nDivs[2];
77  label i = ij/nDivs[1];
78  label j = ij-i*nDivs[1];
79 
80  return labelVector(i, j, k);
81 }
82 
83 
85 (
86  const boundBox& bb,
87  const labelVector& nDivs,
88  const point& pt
89 )
90 {
91  const vector d(bb.span());
92  const point relPt(pt-bb.min());
93 
94  return labelVector
95  (
96  floor(relPt[0]/d[0]*nDivs[0]),
97  floor(relPt[1]/d[1]*nDivs[1]),
98  floor(relPt[2]/d[2]*nDivs[2])
99  );
100 }
101 
102 
104 (
105  const boundBox& bb,
106  const labelVector& nDivs,
107  const label boxI
108 )
109 {
110  // Return midpoint of box indicated by boxI
111  labelVector ids(index3(nDivs, boxI));
112 
113  const vector d(bb.span());
114  const vector sz(d[0]/nDivs[0], d[1]/nDivs[1], d[2]/nDivs[2]);
115 
116  return bb.min()+0.5*sz+vector(sz[0]*ids[0], sz[1]*ids[1], sz[2]*ids[2]);
117 }
118 
119 
121 (
122  PackedList<2>& elems,
123  const boundBox& bb,
124  const labelVector& nDivs,
125  const boundBox& subBb,
126  const unsigned int val
127 )
128 {
129  labelVector minIds(index3(bb, nDivs, subBb.min()));
130  labelVector maxIds(index3(bb, nDivs, subBb.max()));
131 
132  for (direction cmpt = 0; cmpt < 3; cmpt++)
133  {
134  if (maxIds[cmpt] < 0 || minIds[cmpt] > nDivs[cmpt])
135  {
136  return;
137  }
138  }
139 
140  labelVector maxIndex(labelVector(nDivs[0]-1, nDivs[1]-1, nDivs[2]-1));
141  minIds = max(labelVector::zero, minIds);
142  maxIds = min(maxIndex, maxIds);
143 
144  for (label i = minIds[0]; i <= maxIds[0]; i++)
145  {
146  for (label j = minIds[1]; j <= maxIds[1]; j++)
147  {
148  for (label k = minIds[2]; k <= maxIds[2]; k++)
149  {
150  label i1 = index(nDivs, labelVector(i, j, k));
151  elems[i1] = val;
152  }
153  }
154  }
155 }
156 
157 
159 (
160  const fvMesh& mesh,
161  const vector& smallVec,
162 
163  const boundBox& bb,
164  const labelVector& nDivs,
166 
167  const labelList& cellMap,
168  labelList& patchCellTypes
169 )
170 {
171  // Mark all voxels that overlap the bounding box of any patch
172 
173  const fvBoundaryMesh& pbm = mesh.boundary();
174 
175  patchTypes = patchCellType::OTHER;
176 
177  // Mark wall boundaries
178  forAll(pbm, patchI)
179  {
180  const fvPatch& fvp = pbm[patchI];
181  const labelList& fc = fvp.faceCells();
182 
183  if (!fvPatch::constraintType(fvp.type()))
184  {
185  //Info<< "Marking cells on proper patch " << fvp.name()
186  // << " with type " << fvp.type() << endl;
187  const polyPatch& pp = fvp.patch();
188  forAll(pp, i)
189  {
190  // Mark in overall patch types
191  patchCellTypes[cellMap[fc[i]]] = patchCellType::PATCH;
192 
193  // Mark in voxel mesh
194  boundBox faceBb(pp.points(), pp[i], false);
195  faceBb.min() -= smallVec;
196  faceBb.max() += smallVec;
197 
198  if (bb.overlaps(faceBb))
199  {
200  fill(patchTypes, bb, nDivs, faceBb, patchCellType::PATCH);
201  }
202  }
203  }
204  }
205 
206  // Override with overset boundaries
207  forAll(pbm, patchI)
208  {
209  const fvPatch& fvp = pbm[patchI];
210  const labelList& fc = fvp.faceCells();
211 
212  if (isA<oversetFvPatch>(fvp))
213  {
214  //Info<< "Marking cells on overset patch " << fvp.name() << endl;
215  const polyPatch& pp = fvp.patch();
216  forAll(pp, i)
217  {
218  // Mark in overall patch types
219  patchCellTypes[cellMap[fc[i]]] = patchCellType::OVERSET;
220 
221  // Mark in voxel mesh
222  boundBox faceBb(pp.points(), pp[i], false);
223  faceBb.min() -= smallVec;
224  faceBb.max() += smallVec;
225 
226  if (bb.overlaps(faceBb))
227  {
228  fill(patchTypes, bb, nDivs, faceBb, patchCellType::OVERSET);
229  }
230  }
231  }
232  }
233 }
234 
235 
237 (
238  const primitiveMesh& mesh,
239  const label celli
240 )
241 {
242  const cellList& cells = mesh.cells();
243  const faceList& faces = mesh.faces();
244  const pointField& points = mesh.points();
245 
246  treeBoundBox bb
247  (
248  vector(GREAT, GREAT, GREAT),
249  vector(-GREAT, -GREAT, -GREAT)
250  );
251 
252  const cell& cFaces = cells[celli];
253 
254  forAll(cFaces, cFacei)
255  {
256  const face& f = faces[cFaces[cFacei]];
257 
258  forAll(f, fp)
259  {
260  const point& p = points[f[fp]];
261 
262  bb.min() = min(bb.min(), p);
263  bb.max() = max(bb.max(), p);
264  }
265  }
266  return bb;
267 }
268 
269 
271 (
272  const boundBox& bb,
273  const labelVector& nDivs,
274  const PackedList<2>& vals,
275  const treeBoundBox& subBb,
276  const unsigned int val
277 )
278 {
279  // Checks if subBb overlaps any voxel set to val
280 
281  labelVector minIds(index3(bb, nDivs, subBb.min()));
282  labelVector maxIds(index3(bb, nDivs, subBb.max()));
283 
284  for (direction cmpt = 0; cmpt < 3; cmpt++)
285  {
286  if (maxIds[cmpt] < 0 || minIds[cmpt] > nDivs[cmpt])
287  {
288  return false;
289  }
290  }
291 
292  labelVector maxIndex(labelVector(nDivs[0]-1, nDivs[1]-1, nDivs[2]-1));
293  minIds = max(labelVector::zero, minIds);
294  maxIds = min(maxIndex, maxIds);
295 
296  for (label i = minIds[0]; i <= maxIds[0]; i++)
297  {
298  for (label j = minIds[1]; j <= maxIds[1]; j++)
299  {
300  for (label k = minIds[2]; k <= maxIds[2]; k++)
301  {
302  label i1 = index(nDivs, labelVector(i, j, k));
303  if (vals[i1] == patchCellType::PATCH)
304  {
305  return true;
306  }
307  }
308  }
309  }
310  return false;
311 }
312 
313 
315 (
316  PstreamBuffers& pBufs,
317 
319 
320  const List<treeBoundBoxList>& patchBb,
321  const List<labelVector>& patchDivisions,
322  const PtrList<PackedList<2>>& patchParts,
323 
324  const label srcI,
325  const label tgtI,
326  labelList& allCellTypes
327 ) const
328 {
329  const treeBoundBoxList& srcPatchBbs = patchBb[srcI];
330  const treeBoundBoxList& tgtPatchBbs = patchBb[tgtI];
331  const labelList& tgtCellMap = meshParts[tgtI].cellMap();
332 
333  // 1. do processor-local src-tgt patch overlap
334  {
335  const treeBoundBox& srcPatchBb = srcPatchBbs[Pstream::myProcNo()];
336  const treeBoundBox& tgtPatchBb = tgtPatchBbs[Pstream::myProcNo()];
337 
338  if (srcPatchBb.overlaps(tgtPatchBb))
339  {
340  const PackedList<2>& srcPatchTypes = patchParts[srcI];
341  const labelVector& zoneDivs = patchDivisions[srcI];
342 
343  forAll(tgtCellMap, tgtCelli)
344  {
345  label celli = tgtCellMap[tgtCelli];
346  treeBoundBox cBb(cellBb(mesh_, celli));
347  cBb.min() -= smallVec_;
348  cBb.max() += smallVec_;
349 
350  if
351  (
352  overlaps
353  (
354  srcPatchBb,
355  zoneDivs,
356  srcPatchTypes,
357  cBb,
359  )
360  )
361  {
362  allCellTypes[celli] = HOLE;
363  }
364  }
365  }
366  }
367 
368 
369  // 2. Send over srcMesh bits that overlap tgt and do calculation
370  pBufs.clear();
371  for (label procI = 0; procI < Pstream::nProcs(); procI++)
372  {
373  if (procI != Pstream::myProcNo())
374  {
375  const treeBoundBox& srcPatchBb = srcPatchBbs[Pstream::myProcNo()];
376  const treeBoundBox& tgtPatchBb = tgtPatchBbs[procI];
377 
378  if (srcPatchBb.overlaps(tgtPatchBb))
379  {
380  // Send over complete patch voxel map. Tbd: could
381  // subset
382  UOPstream os(procI, pBufs);
383  os << srcPatchBb << patchDivisions[srcI] << patchParts[srcI];
384  }
385  }
386  }
387  pBufs.finishedSends();
388  for (label procI = 0; procI < Pstream::nProcs(); procI++)
389  {
390  if (procI != Pstream::myProcNo())
391  {
392  //const treeBoundBox& srcBb = srcBbs[procI];
393  const treeBoundBox& srcPatchBb = srcPatchBbs[procI];
394  const treeBoundBox& tgtPatchBb = tgtPatchBbs[Pstream::myProcNo()];
395 
396  if (srcPatchBb.overlaps(tgtPatchBb))
397  {
398  UIPstream is(procI, pBufs);
399  {
400  treeBoundBox receivedBb(is);
401  if (srcPatchBb != receivedBb)
402  {
404  << "proc:" << procI
405  << " srcPatchBb:" << srcPatchBb
406  << " receivedBb:" << receivedBb
407  << exit(FatalError);
408  }
409  }
410  const labelVector zoneDivs(is);
411  const PackedList<2> srcPatchTypes(is);
412 
413  forAll(tgtCellMap, tgtCelli)
414  {
415  label celli = tgtCellMap[tgtCelli];
416  treeBoundBox cBb(cellBb(mesh_, celli));
417  cBb.min() -= smallVec_;
418  cBb.max() += smallVec_;
419  if
420  (
421  overlaps
422  (
423  srcPatchBb,
424  zoneDivs,
425  srcPatchTypes,
426  cBb,
428  )
429  )
430  {
431  allCellTypes[celli] = HOLE;
432  }
433  }
434  }
435  }
436  }
437 }
438 
439 
441 (
442  const label destMesh,
443  const label currentDonorMesh,
444  const label newDonorMesh
445 ) const
446 {
447  // This determines for multiple overlapping meshes which one provides
448  // the best donors. Is very basic and only looks at indices of meshes:
449  // - 'nearest' mesh index wins, i.e. on mesh 0 it preferentially uses donors
450  // from mesh 1 over mesh 2 (if applicable)
451  // - if same 'distance' the highest mesh wins. So on mesh 1 it
452  // preferentially uses donors from mesh 2 over mesh 0. This particular
453  // rule helps to avoid some interpolation loops where mesh 1 uses donors
454  // from mesh 0 (usually the background) but mesh 0 then uses
455  // donors from 1.
456 
457  if (currentDonorMesh == -1)
458  {
459  return true;
460  }
461  else
462  {
463  const label currentDist = mag(currentDonorMesh-destMesh);
464  const label newDist = mag(newDonorMesh-destMesh);
465 
466  if (newDist < currentDist)
467  {
468  return true;
469  }
470  else if (newDist == currentDist && newDonorMesh > currentDonorMesh)
471  {
472  return true;
473  }
474  else
475  {
476  return false;
477  }
478  }
479 }
480 
481 
483 (
484  const globalIndex& globalCells,
485  PstreamBuffers& pBufs,
488 
489  const labelList& allCellTypes,
490 
491  const label srcI,
492  const label tgtI,
493  labelListList& allStencil,
494  labelList& allDonor
495 ) const
496 {
497  const treeBoundBoxList& srcBbs = meshBb[srcI];
498  const treeBoundBoxList& tgtBbs = meshBb[tgtI];
499 
500  const fvMesh& srcMesh = meshParts[srcI].subMesh();
501  const labelList& srcCellMap = meshParts[srcI].cellMap();
502  const fvMesh& tgtMesh = meshParts[tgtI].subMesh();
503  const pointField& tgtCc = tgtMesh.cellCentres();
504  const labelList& tgtCellMap = meshParts[tgtI].cellMap();
505 
506  // 1. do processor-local src/tgt overlap
507  {
508  labelList tgtToSrcAddr;
509  waveMethod::calculate(tgtMesh, srcMesh, tgtToSrcAddr);
510  forAll(tgtCellMap, tgtCelli)
511  {
512  label srcCelli = tgtToSrcAddr[tgtCelli];
513  if (srcCelli != -1 && allCellTypes[srcCellMap[srcCelli]] != HOLE)
514  {
515  label celli = tgtCellMap[tgtCelli];
516 
517  // TBD: check for multiple donors. Maybe better one? For
518  // now check 'nearer' mesh
519  if (betterDonor(tgtI, allDonor[celli], srcI))
520  {
521  label globalDonor =
522  globalCells.toGlobal(srcCellMap[srcCelli]);
523  allStencil[celli].setSize(1);
524  allStencil[celli][0] = globalDonor;
525  allDonor[celli] = srcI;
526  }
527  }
528  }
529  }
530 
531 
532  // 2. Send over tgtMesh bits that overlap src and do calculation on
533  // srcMesh.
534 
535 
536  // (remote) processors where the tgt overlaps my src
537  DynamicList<label> tgtOverlapProcs(Pstream::nProcs());
538  // (remote) processors where the src overlaps my tgt
539  DynamicList<label> srcOverlapProcs(Pstream::nProcs());
540  for (label procI = 0; procI < Pstream::nProcs(); procI++)
541  {
542  if (procI != Pstream::myProcNo())
543  {
544  if (tgtBbs[procI].overlaps(srcBbs[Pstream::myProcNo()]))
545  {
546  tgtOverlapProcs.append(procI);
547  }
548  if (srcBbs[procI].overlaps(tgtBbs[Pstream::myProcNo()]))
549  {
550  srcOverlapProcs.append(procI);
551  }
552  }
553  }
554 
555 
556 
557  // Indices of tgtcells to send over to each processor
558  List<DynamicList<label>> tgtSendCells(Pstream::nProcs());
559  forAll(srcOverlapProcs, i)
560  {
561  label procI = srcOverlapProcs[i];
562  tgtSendCells[procI].reserve(tgtMesh.nCells()/srcOverlapProcs.size());
563  }
564 
565 
566  forAll(tgtCellMap, tgtCelli)
567  {
568  label celli = tgtCellMap[tgtCelli];
569  if (srcOverlapProcs.size())
570  {
571  treeBoundBox subBb(cellBb(mesh_, celli));
572  subBb.min() -= smallVec_;
573  subBb.max() += smallVec_;
574 
575  forAll(srcOverlapProcs, i)
576  {
577  label procI = srcOverlapProcs[i];
578  if (subBb.overlaps(srcBbs[procI]))
579  {
580  tgtSendCells[procI].append(tgtCelli);
581  }
582  }
583  }
584  }
585 
586  // Send target cell centres to overlapping processors
587  pBufs.clear();
588 
589  forAll(srcOverlapProcs, i)
590  {
591  label procI = srcOverlapProcs[i];
592  const labelList& cellIDs = tgtSendCells[procI];
593 
594  UOPstream os(procI, pBufs);
595  os << UIndirectList<point>(tgtCc, cellIDs);
596  }
597  pBufs.finishedSends();
598 
599  // Receive bits of target processors; find; send back
600  (void)srcMesh.tetBasePtIs();
601  forAll(tgtOverlapProcs, i)
602  {
603  label procI = tgtOverlapProcs[i];
604 
605  UIPstream is(procI, pBufs);
606  pointList samples(is);
607 
608  labelList donors(samples.size(), -1);
609  forAll(samples, sampleI)
610  {
611  const point& sample = samples[sampleI];
612  label srcCelli = srcMesh.findCell(sample, polyMesh::CELL_TETS);
613  if (srcCelli != -1 && allCellTypes[srcCellMap[srcCelli]] != HOLE)
614  {
615  donors[sampleI] = globalCells.toGlobal(srcCellMap[srcCelli]);
616  }
617  }
618 
619  // Use same pStreamBuffers to send back.
620  UOPstream os(procI, pBufs);
621  os << donors;
622  }
623  pBufs.finishedSends();
624 
625  forAll(srcOverlapProcs, i)
626  {
627  label procI = srcOverlapProcs[i];
628  const labelList& cellIDs = tgtSendCells[procI];
629 
630  UIPstream is(procI, pBufs);
631  labelList donors(is);
632 
633  if (donors.size() != cellIDs.size())
634  {
635  FatalErrorInFunction<< "problem : cellIDs:" << cellIDs.size()
636  << " donors:" << donors.size() << abort(FatalError);
637  }
638 
639  forAll(donors, donorI)
640  {
641  label globalDonor = donors[donorI];
642 
643  if (globalDonor != -1)
644  {
645  label celli = tgtCellMap[cellIDs[donorI]];
646 
647  // TBD: check for multiple donors. Maybe better one? For
648  // now check 'nearer' mesh
649  if (betterDonor(tgtI, allDonor[celli], srcI))
650  {
651  allStencil[celli].setSize(1);
652  allStencil[celli][0] = globalDonor;
653  allDonor[celli] = srcI;
654  }
655  }
656  }
657  }
658 }
659 
660 
661 //void Foam::cellCellStencils::inverseDistance::uncompactedRegionSplit
662 //(
663 // const fvMesh& mesh,
664 // const globalIndex& globalFaces,
665 // const label nZones,
666 // const labelList& zoneID,
667 // const labelList& cellTypes,
668 // const boolList& isBlockedFace,
669 // labelList& cellRegion
670 //) const
671 //{
672 // // Pass 1: locally seed 2 cells per zone (one unblocked, one blocked).
673 // // This avoids excessive numbers of front
674 //
675 // // Field on cells and faces.
676 // List<minData> cellData(mesh.nCells());
677 // List<minData> faceData(mesh.nFaces());
678 //
679 // // Take over blockedFaces by seeding a negative number
680 // // (so is always less than the decomposition)
681 //
682 // forAll(isBlockedFace, facei)
683 // {
684 // if (isBlockedFace[facei])
685 // {
686 // faceData[facei] = minData(-2);
687 // }
688 // }
689 //
690 //
691 // labelList seedFace(nZones, -1);
692 //
693 // const labelList& owner = mesh.faceOwner();
694 // const labelList& neighbour = mesh.faceNeighbour();
695 //
696 // forAll(owner, facei)
697 // {
698 // label own = owner[facei];
699 // if (seedFace[zoneID[own]] == -1)
700 // {
701 // if (cellTypes[own] != HOLE)
702 // {
703 // const cell& cFaces = mesh.cells()[own];
704 // forAll(cFaces, i)
705 // {
706 // if (!isBlockedFace[cFaces[i]])
707 // {
708 // seedFace[zoneID[own]] = cFaces[i];
709 // }
710 // }
711 // }
712 // }
713 // }
714 // forAll(neighbour, facei)
715 // {
716 // label nei = neighbour[facei];
717 // if (seedFace[zoneID[nei]] == -1)
718 // {
719 // if (cellTypes[nei] != HOLE)
720 // {
721 // const cell& cFaces = mesh.cells()[nei];
722 // forAll(cFaces, i)
723 // {
724 // if (!isBlockedFace[cFaces[i]])
725 // {
726 // seedFace[zoneID[nei]] = cFaces[i];
727 // }
728 // }
729 // }
730 // }
731 // }
732 //
733 // DynamicList<label> seedFaces(nZones);
734 // DynamicList<minData> seedData(seedFaces.size());
735 // forAll(seedFace, zonei)
736 // {
737 // if (seedFace[zonei] != -1)
738 // {
739 // seedFaces.append(seedFace[zonei]);
740 // seedData.append(minData(globalFaces.toGlobal(seedFace[zonei])));
741 // }
742 // }
743 //
744 // // Propagate information inwards
745 // FaceCellWave<minData> deltaCalc
746 // (
747 // mesh,
748 // List<labelPair>(),
749 // false, // disable walking through cyclicAMI for backwards
750 // // compatibility
751 // seedFaces,
752 // seedData,
753 // faceData,
754 // cellData,
755 // mesh.globalData().nTotalCells()+1
756 // );
757 //
758 // // Extract
759 // cellRegion.setSize(mesh.nCells());
760 // forAll(cellRegion, celli)
761 // {
762 // if (cellData[celli].valid(deltaCalc.data()))
763 // {
764 // cellRegion[celli] = cellData[celli].data();
765 // }
766 // else
767 // {
768 // // Unvisited cell -> only possible if surrounded by blocked faces.
769 // // If so make up region from any of the faces
770 // const cell& cFaces = mesh.cells()[celli];
771 // label facei = cFaces[0];
772 // cellRegion[celli] = globalFaces.toGlobal(facei);
773 // }
774 // }
775 //}
776 //Foam::autoPtr<Foam::globalIndex>
777 //Foam::cellCellStencils::inverseDistance::compactedRegionSplit
778 //(
779 // const fvMesh& mesh,
780 // const globalIndex& globalRegions,
781 // labelList& cellRegion
782 //) const
783 //{
784 // // Now our cellRegion will have
785 // // - non-local regions (i.e. originating from other processors)
786 // // - non-compact locally originating regions
787 // // so we'll need to compact
788 //
789 // // 4a: count per originating processor the number of regions
790 // labelList nOriginating(Pstream::nProcs(), Zero);
791 // {
792 // labelHashSet haveRegion(mesh.nCells()/8);
793 //
794 // forAll(cellRegion, celli)
795 // {
796 // label region = cellRegion[celli];
797 //
798 // // Count originating processor. Use isLocal as efficiency since
799 // // most cells are locally originating.
800 // if (globalRegions.isLocal(region))
801 // {
802 // if (haveRegion.insert(region))
803 // {
804 // nOriginating[Pstream::myProcNo()]++;
805 // }
806 // }
807 // else
808 // {
809 // label proci = globalRegions.whichProcID(region);
810 // if (haveRegion.insert(region))
811 // {
812 // nOriginating[proci]++;
813 // }
814 // }
815 // }
816 // }
817 //
818 // if (debug)
819 // {
820 // Pout<< "Counted " << nOriginating[Pstream::myProcNo()]
821 // << " local regions." << endl;
822 // }
823 //
824 //
825 // // Global numbering for compacted local regions
826 // autoPtr<globalIndex> globalCompactPtr
827 // (
828 // new globalIndex(nOriginating[Pstream::myProcNo()])
829 // );
830 // const globalIndex& globalCompact = globalCompactPtr();
831 //
832 //
833 // // 4b: renumber
834 // // Renumber into compact indices. Note that since we've already made
835 // // all regions global we now need a Map to store the compacting
836 // // information
837 // // instead of a labelList - otherwise we could have used a straight
838 // // labelList.
839 //
840 // // Local compaction map
841 // Map<label> globalToCompact(2*nOriginating[Pstream::myProcNo()]);
842 // // Remote regions we want the compact number for
843 // List<labelHashSet> nonLocal(Pstream::nProcs());
844 // forAll(nonLocal, proci)
845 // {
846 // if (proci != Pstream::myProcNo())
847 // {
848 // nonLocal[proci].resize(2*nOriginating[proci]);
849 // }
850 // }
851 //
852 // forAll(cellRegion, celli)
853 // {
854 // label region = cellRegion[celli];
855 // if (globalRegions.isLocal(region))
856 // {
857 // // Insert new compact region (if not yet present)
858 // globalToCompact.insert
859 // (
860 // region,
861 // globalCompact.toGlobal(globalToCompact.size())
862 // );
863 // }
864 // else
865 // {
866 // nonLocal[globalRegions.whichProcID(region)].insert(region);
867 // }
868 // }
869 //
870 //
871 // // Now we have all the local regions compacted. Now we need to get the
872 // // non-local ones from the processors to whom they are local.
873 // // Convert the nonLocal (labelHashSets) to labelLists.
874 //
875 // labelListList sendNonLocal(Pstream::nProcs());
876 // forAll(sendNonLocal, proci)
877 // {
878 // sendNonLocal[proci] = nonLocal[proci].toc();
879 // }
880 //
881 // if (debug)
882 // {
883 // forAll(sendNonLocal, proci)
884 // {
885 // Pout<< " from processor " << proci
886 // << " want " << sendNonLocal[proci].size()
887 // << " region numbers." << endl;
888 // }
889 // Pout<< endl;
890 // }
891 //
892 //
893 // // Get the wanted region labels into recvNonLocal
894 // labelListList recvNonLocal;
895 // Pstream::exchange<labelList, label>(sendNonLocal, recvNonLocal);
896 //
897 // // Now we have the wanted compact region labels that proci wants in
898 // // recvNonLocal[proci]. Construct corresponding list of compact
899 // // region labels to send back.
900 //
901 // labelListList sendWantedLocal(Pstream::nProcs());
902 // forAll(recvNonLocal, proci)
903 // {
904 // const labelList& nonLocal = recvNonLocal[proci];
905 // sendWantedLocal[proci].setSize(nonLocal.size());
906 //
907 // forAll(nonLocal, i)
908 // {
909 // sendWantedLocal[proci][i] = globalToCompact[nonLocal[i]];
910 // }
911 // }
912 //
913 //
914 // // Send back (into recvNonLocal)
915 // recvNonLocal.clear();
916 // Pstream::exchange<labelList, label>(sendWantedLocal, recvNonLocal);
917 // sendWantedLocal.clear();
918 //
919 // // Now recvNonLocal contains for every element in setNonLocal the
920 // // corresponding compact number. Insert these into the local compaction
921 // // map.
922 //
923 // forAll(recvNonLocal, proci)
924 // {
925 // const labelList& wantedRegions = sendNonLocal[proci];
926 // const labelList& compactRegions = recvNonLocal[proci];
927 //
928 // forAll(wantedRegions, i)
929 // {
930 // globalToCompact.insert(wantedRegions[i], compactRegions[i]);
931 // }
932 // }
933 //
934 // // Finally renumber the regions
935 // forAll(cellRegion, celli)
936 // {
937 // cellRegion[celli] = globalToCompact[cellRegion[celli]];
938 // }
939 //
940 // return globalCompactPtr;
941 //}
942 
943 
945 (
946  const globalIndex& globalCells,
947  const fvMesh& mesh,
948  const labelList& zoneID,
949  const labelListList& stencil,
951 ) const
952 {
953  const fvBoundaryMesh& pbm = mesh.boundary();
954  const labelList& own = mesh.faceOwner();
955  const labelList& nei = mesh.faceNeighbour();
956 
957 
958  // The input cellTypes will be
959  // - HOLE : cell part covered by other-mesh patch
960  // - INTERPOLATED : cell fully covered by other-mesh patch
961  // or next to 'overset' patch
962  // - CALCULATED : otherwise
963  //
964  // so we start a walk from our patches and any cell we cannot reach
965  // (because we walk is stopped by other-mesh patch) is a hole.
966 
967 
968  DebugInfo<< FUNCTION_NAME << " : Starting hole flood filling" << endl;
969 
970  DebugInfo<< FUNCTION_NAME << " : Starting hole cells : "
971  << findIndices(cellTypes, HOLE).size() << endl;
972 
973  boolList isBlockedFace(mesh.nFaces(), false);
974  label nBlocked = 0;
975 
976  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
977  {
978  label ownType = cellTypes[own[faceI]];
979  label neiType = cellTypes[nei[faceI]];
980  if
981  (
982  (ownType == HOLE && neiType != HOLE)
983  || (ownType != HOLE && neiType == HOLE)
984  )
985  {
986  isBlockedFace[faceI] = true;
987  nBlocked++;
988  }
989  }
990  DebugInfo<< FUNCTION_NAME << " : Marked internal hole boundaries : "
991  << nBlocked << endl;
992 
993 
994  labelList nbrCellTypes;
995  syncTools::swapBoundaryCellList(mesh, cellTypes, nbrCellTypes);
996 
997  for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
998  {
999  label ownType = cellTypes[own[faceI]];
1000  label neiType = nbrCellTypes[faceI-mesh.nInternalFaces()];
1001 
1002  if
1003  (
1004  (ownType == HOLE && neiType != HOLE)
1005  || (ownType != HOLE && neiType == HOLE)
1006  )
1007  {
1008  isBlockedFace[faceI] = true;
1009  nBlocked++;
1010  }
1011  }
1012 
1013  DebugInfo<< FUNCTION_NAME << " : Marked all hole boundaries : "
1014  << nBlocked << endl;
1015 
1016  // Determine regions
1017  regionSplit cellRegion(mesh, isBlockedFace);
1018  const label nRegions = cellRegion.nRegions();
1019 
1020  //labelList cellRegion;
1021  //label nRegions = -1;
1022  //{
1023  // const globalIndex globalFaces(mesh.nFaces());
1024  // uncompactedRegionSplit
1025  // (
1026  // mesh,
1027  // globalFaces,
1028  // gMax(zoneID)+1,
1029  // zoneID,
1030  // cellTypes,
1031  // isBlockedFace,
1032  // cellRegion
1033  // );
1034  // autoPtr<globalIndex> globalRegions
1035  // (
1036  // compactedRegionSplit
1037  // (
1038  // mesh,
1039  // globalFaces,
1040  // cellRegion
1041  // )
1042  // );
1043  // nRegions = globalRegions().size();
1044  //}
1045  DebugInfo<< FUNCTION_NAME << " : Determined regions : "
1046  << nRegions << endl;
1047 
1048  //Info<< typeName << " : detected " << nRegions
1049  // << " mesh regions after overset" << nl << endl;
1050 
1051 
1052 
1053  // Now we'll have a mesh split according to where there are cells
1054  // covered by the other-side patches. See what we can reach from our
1055  // real patches
1056 
1057  // 0 : region not yet determined
1058  // 1 : borders blockage so is not ok (but can be overridden by real
1059  // patch)
1060  // 2 : has real patch in it so is reachable
1061  labelList regionType(nRegions, Zero);
1062 
1063 
1064  // See if any regions borders blockage. Note: isBlockedFace is already
1065  // parallel synchronised.
1066  {
1067  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
1068  {
1069  if (isBlockedFace[faceI])
1070  {
1071  label ownRegion = cellRegion[own[faceI]];
1072 
1073  if (cellTypes[own[faceI]] != HOLE)
1074  {
1075  if (regionType[ownRegion] == 0)
1076  {
1077  regionType[ownRegion] = 1;
1078  }
1079  }
1080 
1081  label neiRegion = cellRegion[nei[faceI]];
1082 
1083  if (cellTypes[nei[faceI]] != HOLE)
1084  {
1085  if (regionType[neiRegion] == 0)
1086  {
1087  regionType[neiRegion] = 1;
1088  }
1089  }
1090  }
1091  }
1092  for
1093  (
1094  label faceI = mesh.nInternalFaces();
1095  faceI < mesh.nFaces();
1096  faceI++
1097  )
1098  {
1099  if (isBlockedFace[faceI])
1100  {
1101  label ownRegion = cellRegion[own[faceI]];
1102 
1103  if (regionType[ownRegion] == 0)
1104  {
1105  regionType[ownRegion] = 1;
1106  }
1107  }
1108  }
1109  }
1110 
1111 
1112  // Override with real patches
1113  forAll(pbm, patchI)
1114  {
1115  const fvPatch& fvp = pbm[patchI];
1116 
1117  if (isA<oversetFvPatch>(fvp))
1118  {}
1119  else if (!fvPatch::constraintType(fvp.type()))
1120  {
1121  const labelList& fc = fvp.faceCells();
1122  forAll(fc, i)
1123  {
1124  label regionI = cellRegion[fc[i]];
1125 
1126  if (cellTypes[fc[i]] != HOLE && regionType[regionI] != 2)
1127  {
1128  regionType[regionI] = 2;
1129  }
1130  }
1131  }
1132  }
1133 
1134  DebugInfo<< FUNCTION_NAME << " : Done local analysis" << endl;
1135 
1136  // Now we've handled
1137  // - cells next to blocked cells
1138  // - coupled boundaries
1139  // Only thing to handle is the interpolation between regions
1140 
1141 
1142  labelListList compactStencil(stencil);
1143  List<Map<label>> compactMap;
1144  mapDistribute map(globalCells, compactStencil, compactMap);
1145 
1146  DebugInfo<< FUNCTION_NAME << " : Converted stencil into compact form"
1147  << endl;
1148 
1149 
1150  while (true)
1151  {
1152  // Synchronise region status on processors
1153  // (could instead swap status through processor patches)
1154  Pstream::listCombineGather(regionType, maxEqOp<label>());
1155  Pstream::listCombineScatter(regionType);
1156 
1157  DebugInfo<< FUNCTION_NAME << " : Gathered region type" << endl;
1158 
1159  // Communicate region status through interpolative cells
1160  labelList cellRegionType(labelUIndList(regionType, cellRegion));
1161  map.distribute(cellRegionType);
1162 
1163  DebugInfo<< FUNCTION_NAME << " : Interpolated region type" << endl;
1164 
1165 
1166 
1167  label nChanged = 0;
1168  forAll(pbm, patchI)
1169  {
1170  const fvPatch& fvp = pbm[patchI];
1171 
1172  if (isA<oversetFvPatch>(fvp))
1173  {
1174  const labelUList& fc = fvp.faceCells();
1175  forAll(fc, i)
1176  {
1177  label cellI = fc[i];
1178  label regionI = cellRegion[cellI];
1179 
1180  if (regionType[regionI] != 2)
1181  {
1182  const labelList& slots = compactStencil[cellI];
1183  forAll(slots, i)
1184  {
1185  label otherType = cellRegionType[slots[i]];
1186 
1187  if (otherType == 2)
1188  {
1189  //Pout<< "Reachable through interpolation : "
1190  // << regionI << " at cell "
1191  // << mesh.cellCentres()[cellI] << endl;
1192  regionType[regionI] = 2;
1193  nChanged++;
1194  break;
1195  }
1196  }
1197  }
1198  }
1199  }
1200  }
1201 
1202  reduce(nChanged, sumOp<label>());
1203  DebugInfo<< FUNCTION_NAME << " : Determined regions changed : "
1204  << nChanged << endl;
1205 
1206  if (nChanged == 0)
1207  {
1208  break;
1209  }
1210  }
1211 
1212 
1213  // See which regions have not been visited (regionType == 1)
1214  forAll(cellRegion, cellI)
1215  {
1216  label type = regionType[cellRegion[cellI]];
1217  if (type == 1 && cellTypes[cellI] != HOLE)
1218  {
1219  cellTypes[cellI] = HOLE;
1220  }
1221  }
1222  DebugInfo<< FUNCTION_NAME << " : Finished hole flood filling" << endl;
1223 }
1224 
1225 
1228  const label cellI,
1229  const scalar wantedFraction,
1230  bitSet& isFront,
1231  scalarField& fraction
1232 ) const
1233 {
1234  const cell& cFaces = mesh_.cells()[cellI];
1235  forAll(cFaces, i)
1236  {
1237  label nbrFacei = cFaces[i];
1238  if (fraction[nbrFacei] < wantedFraction)
1239  {
1240  fraction[nbrFacei] = wantedFraction;
1241  isFront.set(nbrFacei);
1242  }
1243  }
1244 }
1245 
1246 
1249  const scalar layerRelax,
1250  const labelListList& allStencil,
1251  labelList& allCellTypes,
1252  scalarField& allWeight
1253 ) const
1254 {
1255  // Current front
1256  bitSet isFront(mesh_.nFaces());
1257 
1258  const fvBoundaryMesh& fvm = mesh_.boundary();
1259 
1260 
1261  // 'overset' patches
1262 
1263  forAll(fvm, patchI)
1264  {
1265  if (isA<oversetFvPatch>(fvm[patchI]))
1266  {
1267  const labelList& fc = fvm[patchI].faceCells();
1268  forAll(fc, i)
1269  {
1270  label cellI = fc[i];
1271  if (allCellTypes[cellI] == INTERPOLATED)
1272  {
1273  // Note that acceptors might have been marked hole if
1274  // there are no donors in which case we do not want to
1275  // walk this out. This is an extreme situation.
1276  isFront.set(fvm[patchI].start()+i);
1277  }
1278  }
1279  }
1280  }
1281 
1282 
1283  // Outside of 'hole' region
1284  {
1285  const labelList& own = mesh_.faceOwner();
1286  const labelList& nei = mesh_.faceNeighbour();
1287 
1288  for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
1289  {
1290  label ownType = allCellTypes[own[faceI]];
1291  label neiType = allCellTypes[nei[faceI]];
1292  if
1293  (
1294  (ownType == HOLE && neiType != HOLE)
1295  || (ownType != HOLE && neiType == HOLE)
1296  )
1297  {
1298  //Pout<< "Front at face:" << faceI
1299  // << " at:" << mesh_.faceCentres()[faceI] << endl;
1300  isFront.set(faceI);
1301  }
1302  }
1303 
1304  labelList nbrCellTypes;
1305  syncTools::swapBoundaryCellList(mesh_, allCellTypes, nbrCellTypes);
1306 
1307  for
1308  (
1309  label faceI = mesh_.nInternalFaces();
1310  faceI < mesh_.nFaces();
1311  faceI++
1312  )
1313  {
1314  label ownType = allCellTypes[own[faceI]];
1315  label neiType = nbrCellTypes[faceI-mesh_.nInternalFaces()];
1316 
1317  if
1318  (
1319  (ownType == HOLE && neiType != HOLE)
1320  || (ownType != HOLE && neiType == HOLE)
1321  )
1322  {
1323  //Pout<< "Front at coupled face:" << faceI
1324  // << " at:" << mesh_.faceCentres()[faceI] << endl;
1325  isFront.set(faceI);
1326  }
1327  }
1328  }
1329 
1330 
1331  // Current interpolation fraction
1332  scalarField fraction(mesh_.nFaces(), Zero);
1333 
1334  forAll(isFront, faceI)
1335  {
1336  if (isFront.test(faceI))
1337  {
1338  fraction[faceI] = 1.0;
1339  }
1340  }
1341 
1342 
1343  while (returnReduce(isFront.any(), orOp<bool>()))
1344  {
1345  // Interpolate cells on front
1346  bitSet newIsFront(mesh_.nFaces());
1347  scalarField newFraction(fraction);
1348  forAll(isFront, faceI)
1349  {
1350  if (isFront.test(faceI))
1351  {
1352  label own = mesh_.faceOwner()[faceI];
1353  if (allCellTypes[own] != HOLE)
1354  {
1355  if (allWeight[own] < fraction[faceI])
1356  {
1357  // Cell wants to become interpolated (if sufficient
1358  // stencil, otherwise becomes hole)
1359  if (allStencil[own].size())
1360  {
1361  allWeight[own] = fraction[faceI];
1362  allCellTypes[own] = INTERPOLATED;
1363  // Add faces of cell (with lower weight) as new
1364  // front
1365  seedCell
1366  (
1367  own,
1368  fraction[faceI]-layerRelax,
1369  newIsFront,
1370  newFraction
1371  );
1372  }
1373  else
1374  {
1375  allWeight[own] = 0.0;
1376  allCellTypes[own] = HOLE;
1377  // Add faces of cell as new front
1378  seedCell
1379  (
1380  own,
1381  1.0,
1382  newIsFront,
1383  newFraction
1384  );
1385  }
1386  }
1387  }
1388  if (mesh_.isInternalFace(faceI))
1389  {
1390  label nei = mesh_.faceNeighbour()[faceI];
1391  if (allCellTypes[nei] != HOLE)
1392  {
1393  if (allWeight[nei] < fraction[faceI])
1394  {
1395  if (allStencil[nei].size())
1396  {
1397  allWeight[nei] = fraction[faceI];
1398  allCellTypes[nei] = INTERPOLATED;
1399  seedCell
1400  (
1401  nei,
1402  fraction[faceI]-layerRelax,
1403  newIsFront,
1404  newFraction
1405  );
1406  }
1407  else
1408  {
1409  allWeight[nei] = 0.0;
1410  allCellTypes[nei] = HOLE;
1411  seedCell
1412  (
1413  nei,
1414  1.0,
1415  newIsFront,
1416  newFraction
1417  );
1418  }
1419  }
1420  }
1421  }
1422  }
1423  }
1424 
1425  syncTools::syncFaceList(mesh_, newIsFront, orEqOp<unsigned int>());
1426  syncTools::syncFaceList(mesh_, newFraction, maxEqOp<scalar>());
1427 
1428  isFront.transfer(newIsFront);
1429  fraction.transfer(newFraction);
1430  }
1431 }
1432 
1433 
1436  const point& sample,
1437  const pointList& donorCcs,
1438  scalarList& weights
1439 ) const
1440 {
1441  // Inverse-distance weighting
1442 
1443  weights.setSize(donorCcs.size());
1444  scalar sum = 0.0;
1445  forAll(donorCcs, i)
1446  {
1447  scalar d = mag(sample-donorCcs[i]);
1448 
1449  if (d > ROOTVSMALL)
1450  {
1451  weights[i] = 1.0/d;
1452  sum += weights[i];
1453  }
1454  else
1455  {
1456  // Short circuit
1457  weights = 0.0;
1458  weights[i] = 1.0;
1459  return;
1460  }
1461  }
1462  forAll(weights, i)
1463  {
1464  weights[i] /= sum;
1465  }
1466 }
1467 
1468 
1471  const globalIndex& globalCells
1472 )
1473 {
1474  // Send cell centre back to donor
1475  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1476  // The complication is that multiple acceptors need the same donor
1477  // (but with different weights obviously)
1478  // So we do multi-pass:
1479  // - send over cc of acceptor for which we want stencil.
1480  // Consistently choose the acceptor with smallest magSqr in case of
1481  // multiple acceptors for the containing cell/donor.
1482  // - find the cell-cells and weights for the donor
1483  // - send back together with the acceptor cc
1484  // - use the acceptor cc to see if it was 'me' that sent it. If so
1485  // mark me as complete so it doesn't get involved in the next loop.
1486  // - loop until all resolved.
1487 
1488  // Special value for unused points
1489  const vector greatPoint(GREAT, GREAT, GREAT);
1490 
1491  boolList isValidDonor(mesh_.nCells(), true);
1492  forAll(cellTypes_, celli)
1493  {
1494  if (cellTypes_[celli] == HOLE)
1495  {
1496  isValidDonor[celli] = false;
1497  }
1498  }
1499 
1500 
1501  // Has acceptor been handled already?
1502  bitSet doneAcceptor(interpolationCells_.size());
1503 
1504  while (true)
1505  {
1506  pointField samples(cellInterpolationMap().constructSize(), greatPoint);
1507 
1508  // Fill remote slots (override old content). We'll find out later
1509  // on which one has won and mark this one in doneAcceptor.
1510  label nSamples = 0;
1511  forAll(interpolationCells_, i)
1512  {
1513  if (!doneAcceptor[i])
1514  {
1515  label cellI = interpolationCells_[i];
1516  const point& cc = mesh_.cellCentres()[cellI];
1517  const labelList& slots = cellStencil_[cellI];
1518 
1519  if (slots.size() != 1)
1520  {
1521  FatalErrorInFunction<< "Problem:" << slots
1522  << abort(FatalError);
1523  }
1524 
1525  forAll(slots, slotI)
1526  {
1527  label elemI = slots[slotI];
1528  //Pout<< " acceptor:" << cellI
1529  // << " at:" << mesh_.cellCentres()[cellI]
1530  // << " global:" << globalCells.toGlobal(cellI)
1531  // << " foudn in donor:" << elemI << endl;
1532  minMagSqrEqOp<point>()(samples[elemI], cc);
1533  }
1534  nSamples++;
1535  }
1536  }
1537 
1538 
1539  if (returnReduce(nSamples, sumOp<label>()) == 0)
1540  {
1541  break;
1542  }
1543 
1544  // Send back to donor. Make sure valid point takes priority
1545  mapDistributeBase::distribute<point, minMagSqrEqOp<point>, flipOp>
1546  (
1547  Pstream::commsTypes::nonBlocking,
1548  List<labelPair>(),
1549  mesh_.nCells(),
1550  cellInterpolationMap().constructMap(),
1551  false,
1552  cellInterpolationMap().subMap(),
1553  false,
1554  samples,
1556  flipOp(), // negateOp
1557  greatPoint // nullValue
1558  );
1559 
1560  // All the donor cells will now have a valid cell centre. Construct a
1561  // stencil for these.
1562 
1563  DynamicList<label> donorCells(mesh_.nCells());
1564  forAll(samples, cellI)
1565  {
1566  if (samples[cellI] != greatPoint)
1567  {
1568  donorCells.append(cellI);
1569  }
1570  }
1571 
1572 
1573  // Get neighbours (global cell and centre) of donorCells.
1574  labelListList donorCellCells(mesh_.nCells());
1575  pointListList donorCellCentres(mesh_.nCells());
1576  globalCellCells
1577  (
1578  globalCells,
1579  mesh_,
1580  isValidDonor,
1581  donorCells,
1582  donorCellCells,
1583  donorCellCentres
1584  );
1585 
1586  // Determine the weights.
1587  scalarListList donorWeights(mesh_.nCells());
1588  forAll(donorCells, i)
1589  {
1590  label cellI = donorCells[i];
1591  const pointList& donorCentres = donorCellCentres[cellI];
1592  stencilWeights
1593  (
1594  samples[cellI],
1595  donorCentres,
1596  donorWeights[cellI]
1597  );
1598  }
1599 
1600  // Transfer the information back to the acceptor:
1601  // - donorCellCells : stencil (with first element the original donor)
1602  // - donorWeights : weights for donorCellCells
1603  cellInterpolationMap().distribute(donorCellCells);
1604  cellInterpolationMap().distribute(donorWeights);
1605  cellInterpolationMap().distribute(samples);
1606 
1607  // Check which acceptor has won and transfer
1608  forAll(interpolationCells_, i)
1609  {
1610  if (!doneAcceptor[i])
1611  {
1612  label cellI = interpolationCells_[i];
1613  const labelList& slots = cellStencil_[cellI];
1614 
1615  if (slots.size() != 1)
1616  {
1617  FatalErrorInFunction << "Problem:" << slots
1618  << abort(FatalError);
1619  }
1620 
1621  label slotI = slots[0];
1622 
1623  // Important: check if the stencil is actually for this cell
1624  if (samples[slotI] == mesh_.cellCentres()[cellI])
1625  {
1626  cellStencil_[cellI].transfer(donorCellCells[slotI]);
1627  cellInterpolationWeights_[cellI].transfer
1628  (
1629  donorWeights[slotI]
1630  );
1631  // Mark cell as being done so it does not get sent over
1632  // again.
1633  doneAcceptor.set(i);
1634  }
1635  }
1636  }
1637  }
1638 
1639  // Re-do the mapDistribute
1640  List<Map<label>> compactMap;
1641  cellInterpolationMap_.reset
1642  (
1643  new mapDistribute
1644  (
1645  globalCells,
1646  cellStencil_,
1647  compactMap
1648  )
1649  );
1650 }
1651 
1652 
1653 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1654 
1655 Foam::cellCellStencils::inverseDistance::inverseDistance
1657  const fvMesh& mesh,
1658  const dictionary& dict,
1659  const bool doUpdate
1660 )
1661 :
1663  dict_(dict),
1664  smallVec_(Zero),
1665  cellTypes_(labelList(mesh.nCells(), CALCULATED)),
1666  interpolationCells_(0),
1667  cellInterpolationMap_(),
1668  cellStencil_(0),
1669  cellInterpolationWeights_(0),
1670  cellInterpolationWeight_
1671  (
1672  IOobject
1673  (
1674  "cellInterpolationWeight",
1675  mesh_.facesInstance(),
1676  mesh_,
1677  IOobject::NO_READ,
1678  IOobject::NO_WRITE,
1679  false
1680  ),
1681  mesh_,
1683  zeroGradientFvPatchScalarField::typeName
1684  )
1685 {
1686  // Protect local fields from interpolation
1687  nonInterpolatedFields_.insert("cellInterpolationWeight");
1688  nonInterpolatedFields_.insert("cellTypes");
1689  nonInterpolatedFields_.insert("maxMagWeight");
1690 
1691  // For convenience also suppress frequently used displacement field
1692  nonInterpolatedFields_.insert("cellDisplacement");
1693  nonInterpolatedFields_.insert("grad(cellDisplacement)");
1694  const word w("snGradCorr(cellDisplacement)");
1695  const word d("((viscosity*faceDiffusivity)*magSf)");
1696  nonInterpolatedFields_.insert("surfaceIntegrate(("+d+"*"+w+"))");
1697 
1698  // Read zoneID
1699  this->zoneID();
1700 
1701  // Read old-time cellTypes
1702  IOobject io
1703  (
1704  "cellTypes",
1705  mesh_.time().timeName(),
1706  mesh_,
1707  IOobject::READ_IF_PRESENT,
1708  IOobject::NO_WRITE,
1709  false
1710  );
1711  if (io.typeHeaderOk<volScalarField>(true))
1712  {
1713  if (debug)
1714  {
1715  Pout<< "Reading cellTypes from time " << mesh_.time().timeName()
1716  << endl;
1717  }
1718 
1719  const volScalarField volCellTypes(io, mesh_);
1720  forAll(volCellTypes, celli)
1721  {
1722  // Round to integer
1723  cellTypes_[celli] = volCellTypes[celli];
1724  }
1725  }
1726 
1727  if (doUpdate)
1728  {
1729  update();
1730  }
1731 }
1732 
1733 
1734 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1735 
1737 {}
1738 
1739 
1740 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1741 
1743 {
1744  scalar layerRelax(dict_.lookupOrDefault("layerRelax", 1.0));
1745 
1746  scalar tol = dict_.lookupOrDefault("tolerance", 1e-10);
1747  smallVec_ = mesh_.bounds().span()*tol;
1748 
1749  const labelIOList& zoneID = this->zoneID();
1750 
1751  label nZones = gMax(zoneID)+1;
1753  forAll(zoneID, cellI)
1754  {
1755  nCellsPerZone[zoneID[cellI]]++;
1756  }
1759 
1760 
1761  const boundBox& allBb(mesh_.bounds());
1762 
1763 
1766 
1767  // Determine zone meshes and bounding boxes
1768  {
1769  // Per processor, per zone the bounding box
1771  procBb[Pstream::myProcNo()].setSize(nZones);
1772 
1773  forAll(meshParts, zonei)
1774  {
1775  meshParts.set
1776  (
1777  zonei,
1778  new fvMeshSubset(mesh_, zonei, zoneID)
1779  );
1780  const fvMesh& subMesh = meshParts[zonei].subMesh();
1781 
1782  // Trigger early evaluation of mesh dimension (in case there are
1783  // zero cells in mesh)
1784  (void)subMesh.nGeometricD();
1785 
1786  if (subMesh.nPoints())
1787  {
1788  procBb[Pstream::myProcNo()][zonei] =
1789  treeBoundBox(subMesh.points());
1790  procBb[Pstream::myProcNo()][zonei].inflate(1e-6);
1791  }
1792  else
1793  {
1794  // No part of zone on this processor. Make up bb.
1795  procBb[Pstream::myProcNo()][zonei] = treeBoundBox
1796  (
1797  allBb.min() - 2*allBb.span(),
1798  allBb.min() - allBb.span()
1799  );
1800  procBb[Pstream::myProcNo()][zonei].inflate(1e-6);
1801  }
1802  }
1803 
1804  Pstream::gatherList(procBb);
1805  Pstream::scatterList(procBb);
1806 
1807  // Move local bounding boxes to per-mesh indexing
1808  forAll(meshBb, zoneI)
1809  {
1810  treeBoundBoxList& bbs = meshBb[zoneI];
1811  bbs.setSize(Pstream::nProcs());
1812  forAll(procBb, procI)
1813  {
1814  bbs[procI] = procBb[procI][zoneI];
1815  }
1816  }
1817  }
1818 
1819 
1820  // Determine patch bounding boxes. These are either global and provided
1821  // by the user or processor-local as a copy of the mesh bounding box.
1822 
1823  List<treeBoundBoxList> patchBb(nZones);
1824  List<labelVector> patchDivisions(nZones);
1825  PtrList<PackedList<2>> patchParts(nZones);
1826  labelList allPatchTypes(mesh_.nCells(), OTHER);
1827 
1828  {
1829  treeBoundBox globalPatchBb;
1830  if (dict_.readIfPresent("searchBox", globalPatchBb))
1831  {
1832  // All processors, all zones have the same bounding box
1833  patchBb = treeBoundBoxList(Pstream::nProcs(), globalPatchBb);
1834  }
1835  else
1836  {
1837  // Use the meshBb (differing per zone, per processor)
1838  patchBb = meshBb;
1839  }
1840  }
1841 
1842  {
1843  labelVector globalDivs;
1844  if (dict_.readIfPresent("searchBoxDivisions", globalDivs))
1845  {
1846  patchDivisions = globalDivs;
1847  }
1848  else
1849  {
1850  const labelVector& dim = mesh_.geometricD();
1851  label nDivs = -1;
1852  if (mesh_.nGeometricD() == 1)
1853  {
1854  nDivs = mesh_.nCells();
1855  }
1856  else if (mesh_.nGeometricD() == 2)
1857  {
1858  nDivs = label(Foam::sqrt(scalar(mesh_.nCells())));
1859  }
1860  else
1861  {
1862  nDivs = label(Foam::cbrt(scalar(mesh_.nCells())));
1863  }
1864 
1865  labelVector v(nDivs, nDivs, nDivs);
1866  forAll(dim, i)
1867  {
1868  if (dim[i] == -1)
1869  {
1870  v[i] = 1;
1871  }
1872  }
1873  patchDivisions = v;
1874  }
1875  }
1876 
1877  forAll(patchParts, zoneI)
1878  {
1879  patchParts.set
1880  (
1881  zoneI,
1882  new PackedList<2>
1883  (
1884  patchDivisions[zoneI][0]
1885  *patchDivisions[zoneI][1]
1886  *patchDivisions[zoneI][2]
1887  )
1888  );
1889  markBoundaries
1890  (
1891  meshParts[zoneI].subMesh(),
1892  smallVec_,
1893 
1894  patchBb[zoneI][Pstream::myProcNo()],
1895  patchDivisions[zoneI],
1896  patchParts[zoneI],
1897 
1898  meshParts[zoneI].cellMap(),
1899  allPatchTypes
1900  );
1901  }
1902 
1903 
1904  // Print a bit
1905  {
1906  Info<< type() << " : detected " << nZones
1907  << " mesh regions" << endl;
1908  Info<< incrIndent;
1909  forAll(nCellsPerZone, zoneI)
1910  {
1911  Info<< indent<< "zone:" << zoneI
1912  << " nCells:" << nCellsPerZone[zoneI]
1913  << " voxels:" << patchDivisions[zoneI]
1914  << " bb:" << patchBb[zoneI][Pstream::myProcNo()]
1915  << endl;
1916  }
1917  Info<< decrIndent;
1918  }
1919 
1920 
1921  // Current best guess for cells. Includes best stencil. Weights should
1922  // add up to volume.
1923  labelList allCellTypes(mesh_.nCells(), CALCULATED);
1924  labelListList allStencil(mesh_.nCells());
1925  // zoneID of donor
1926  labelList allDonorID(mesh_.nCells(), -1);
1927 
1928  const globalIndex globalCells(mesh_.nCells());
1929 
1931 
1932  // Mark holes (in allCellTypes)
1933  for (label srcI = 0; srcI < meshParts.size()-1; srcI++)
1934  {
1935  for (label tgtI = srcI+1; tgtI < meshParts.size(); tgtI++)
1936  {
1937  markPatchesAsHoles
1938  (
1939  pBufs,
1940 
1941  meshParts,
1942 
1943  patchBb,
1944  patchDivisions,
1945  patchParts,
1946 
1947  srcI,
1948  tgtI,
1949  allCellTypes
1950  );
1951  markPatchesAsHoles
1952  (
1953  pBufs,
1954 
1955  meshParts,
1956 
1957  patchBb,
1958  patchDivisions,
1959  patchParts,
1960 
1961  tgtI,
1962  srcI,
1963  allCellTypes
1964  );
1965  }
1966  }
1967 
1968  // Find donors (which are not holes) in allStencil, allDonorID
1969  for (label srcI = 0; srcI < meshParts.size()-1; srcI++)
1970  {
1971  for (label tgtI = srcI+1; tgtI < meshParts.size(); tgtI++)
1972  {
1973  markDonors
1974  (
1975  globalCells,
1976  pBufs,
1977  meshParts,
1978  meshBb,
1979  allCellTypes,
1980 
1981  tgtI,
1982  srcI,
1983  allStencil,
1984  allDonorID
1985  );
1986  markDonors
1987  (
1988  globalCells,
1989  pBufs,
1990  meshParts,
1991  meshBb,
1992  allCellTypes,
1993 
1994  srcI,
1995  tgtI,
1996  allStencil,
1997  allDonorID
1998  );
1999  }
2000  }
2001 
2002  if (debug)
2003  {
2004  tmp<volScalarField> tfld
2005  (
2006  createField(mesh_, "allCellTypes", allCellTypes)
2007  );
2008  tfld().write();
2009  }
2010 
2011  // Use the patch types and weights to decide what to do
2012  forAll(allPatchTypes, cellI)
2013  {
2014  if (allCellTypes[cellI] != HOLE)
2015  {
2016  switch (allPatchTypes[cellI])
2017  {
2018  case OVERSET:
2019  {
2020  // Require interpolation. See if possible.
2021 
2022  if (allStencil[cellI].size())
2023  {
2024  allCellTypes[cellI] = INTERPOLATED;
2025  }
2026  else
2027  {
2028  // If there are no donors we can either set the
2029  // acceptor cell to 'hole' i.e. nothing gets calculated
2030  // if the acceptor cells go outside the donor meshes or
2031  // we can set it to 'calculated' to have something
2032  // like an acmi type behaviour where only covered
2033  // acceptor cell use the interpolation and non-covered
2034  // become calculated. Uncomment below line. Note: this
2035  // should be switchable?
2036  //allCellTypes[cellI] = CALCULATED;
2037 
2038  allCellTypes[cellI] = HOLE;
2039  }
2040  }
2041  }
2042  }
2043  }
2044 
2045  if (debug)
2046  {
2047  tmp<volScalarField> tfld
2048  (
2049  createField(mesh_, "allCellTypes_patch", allCellTypes)
2050  );
2051  tfld().write();
2052  }
2053 
2054 
2055  // Check previous iteration cellTypes_ for any hole->calculated changes
2056  // If so set the cell either to interpolated (if there are donors) or
2057  // holes (if there are no donors). Note that any interpolated cell might
2058  // still be overwritten by the flood filling
2059  {
2060  label nCalculated = 0;
2061 
2062  forAll(cellTypes_, celli)
2063  {
2064  if (allCellTypes[celli] == CALCULATED && cellTypes_[celli] == HOLE)
2065  {
2066  if (allStencil[celli].size() == 0)
2067  {
2068  // Reset to hole
2069  allCellTypes[celli] = HOLE;
2070  allStencil[celli].clear();
2071  }
2072  else
2073  {
2074  allCellTypes[celli] = INTERPOLATED;
2075  nCalculated++;
2076  }
2077  }
2078  }
2079 
2080  if (debug)
2081  {
2082  Pout<< "Detected " << nCalculated << " cells changing from hole"
2083  << " to calculated. Changed to interpolated"
2084  << endl;
2085  }
2086  }
2087 
2088 
2089  // Mark unreachable bits
2090  findHoles(globalCells, mesh_, zoneID, allStencil, allCellTypes);
2091 
2092  if (debug)
2093  {
2094  tmp<volScalarField> tfld
2095  (
2096  createField(mesh_, "allCellTypes_hole", allCellTypes)
2097  );
2098  tfld().write();
2099  }
2100  if (debug)
2101  {
2102  labelList stencilSize(mesh_.nCells());
2103  forAll(allStencil, celli)
2104  {
2105  stencilSize[celli] = allStencil[celli].size();
2106  }
2107  tmp<volScalarField> tfld
2108  (
2109  createField(mesh_, "allStencil_hole", stencilSize)
2110  );
2111  tfld().write();
2112  }
2113 
2114 
2115  // Add buffer interpolation layer(s) around holes
2116  scalarField allWeight(mesh_.nCells(), Zero);
2117  walkFront(layerRelax, allStencil, allCellTypes, allWeight);
2118 
2119  if (debug)
2120  {
2121  tmp<volScalarField> tfld
2122  (
2123  createField(mesh_, "allCellTypes_front", allCellTypes)
2124  );
2125  tfld().write();
2126  }
2127 
2128 
2129  // Convert cell-cell addressing to stencil in compact notation
2130 
2131  cellTypes_.transfer(allCellTypes);
2132  cellStencil_.setSize(mesh_.nCells());
2133  cellInterpolationWeights_.setSize(mesh_.nCells());
2134  DynamicList<label> interpolationCells;
2135  forAll(cellTypes_, cellI)
2136  {
2137  if (cellTypes_[cellI] == INTERPOLATED)
2138  {
2139  cellStencil_[cellI].transfer(allStencil[cellI]);
2140  cellInterpolationWeights_[cellI].setSize(1);
2141  cellInterpolationWeights_[cellI][0] = 1.0;
2142  interpolationCells.append(cellI);
2143  }
2144  else
2145  {
2146  cellStencil_[cellI].clear();
2147  cellInterpolationWeights_[cellI].clear();
2148  }
2149  }
2150  interpolationCells_.transfer(interpolationCells);
2151 
2152  List<Map<label>> compactMap;
2153  cellInterpolationMap_.reset
2154  (
2155  new mapDistribute(globalCells, cellStencil_, compactMap)
2156  );
2157  cellInterpolationWeight_.transfer(allWeight);
2159  <
2162  >(cellInterpolationWeight_.boundaryFieldRef(), false);
2163 
2164 
2165  if (debug&2)
2166  {
2167  // Dump mesh
2168  mesh_.time().write();
2169 
2170  // Dump stencil
2171  mkDir(mesh_.time().timePath());
2172  OBJstream str(mesh_.time().timePath()/"injectionStencil.obj");
2173  Pout<< type() << " : dumping injectionStencil to "
2174  << str.name() << endl;
2175  pointField cc(mesh_.cellCentres());
2176  cellInterpolationMap().distribute(cc);
2177 
2178  forAll(cellStencil_, celli)
2179  {
2180  const labelList& slots = cellStencil_[celli];
2181  if (slots.size())
2182  {
2183  const point& accCc = mesh_.cellCentres()[celli];
2184  forAll(slots, i)
2185  {
2186  const point& donorCc = cc[slots[i]];
2187  str.write(linePointRef(accCc, 0.1*accCc+0.9*donorCc));
2188  }
2189  }
2190  }
2191  }
2192 
2193 
2194  // Extend stencil to get inverse distance weighted neighbours
2195  createStencil(globalCells);
2196 
2197 
2198  if (debug&2)
2199  {
2200  // Dump weight
2201  cellInterpolationWeight_.instance() = mesh_.time().timeName();
2202  cellInterpolationWeight_.write();
2203 
2204  // Dump max weight
2205  {
2206  scalarField maxMagWeight(mesh_.nCells(), Zero);
2207  forAll(cellStencil_, celli)
2208  {
2209  const scalarList& wghts = cellInterpolationWeights_[celli];
2210  forAll(wghts, i)
2211  {
2212  if (mag(wghts[i]) > mag(maxMagWeight[celli]))
2213  {
2214  maxMagWeight[celli] = wghts[i];
2215  }
2216  }
2217  if (mag(maxMagWeight[celli]) > 1)
2218  {
2219  const pointField& cc = mesh_.cellCentres();
2220  Pout<< "cell:" << celli
2221  << " at:" << cc[celli]
2222  << " zone:" << zoneID[celli]
2223  << " donors:" << cellStencil_[celli]
2224  << " weights:" << wghts
2225  << " coords:"
2226  << UIndirectList<point>(cc, cellStencil_[celli])
2227  << " donorZone:"
2228  << UIndirectList<label>(zoneID, cellStencil_[celli])
2229  << endl;
2230  }
2231  }
2232  tmp<volScalarField> tfld
2233  (
2234  createField(mesh_, "maxMagWeight", maxMagWeight)
2235  );
2237  <
2240  >(tfld.ref().boundaryFieldRef(), false);
2241  tfld().write();
2242  }
2243 
2244  // Dump cell types
2245  {
2246  tmp<volScalarField> tfld
2247  (
2248  createField(mesh_, "cellTypes", cellTypes_)
2249  );
2250  //tfld.ref().correctBoundaryConditions();
2252  <
2255  >(tfld.ref().boundaryFieldRef(), false);
2256  tfld().write();
2257  }
2258 
2259 
2260  // Dump stencil
2261  mkDir(mesh_.time().timePath());
2262  OBJstream str(mesh_.time().timePath()/"stencil.obj");
2263  Pout<< type() << " : dumping to " << str.name() << endl;
2264  pointField cc(mesh_.cellCentres());
2265  cellInterpolationMap().distribute(cc);
2266 
2267  forAll(cellStencil_, celli)
2268  {
2269  const labelList& slots = cellStencil_[celli];
2270  if (slots.size())
2271  {
2272  const point& accCc = mesh_.cellCentres()[celli];
2273  forAll(slots, i)
2274  {
2275  const point& donorCc = cc[slots[i]];
2276  str.write(linePointRef(accCc, 0.1*accCc+0.9*donorCc));
2277  }
2278  }
2279  }
2280  }
2281 
2282  // Print some stats
2283  {
2284  labelList nCells(count(3, cellTypes_));
2285 
2286  label nLocal = 0;
2287  label nMixed = 0;
2288  label nRemote = 0;
2289  forAll(interpolationCells_, i)
2290  {
2291  label celli = interpolationCells_[i];
2292  const labelList& slots = cellStencil_[celli];
2293 
2294  bool hasLocal = false;
2295  bool hasRemote = false;
2296 
2297  forAll(slots, sloti)
2298  {
2299  if (slots[sloti] >= mesh_.nCells())
2300  {
2301  hasRemote = true;
2302  }
2303  else
2304  {
2305  hasLocal = true;
2306  }
2307  }
2308 
2309  if (hasRemote)
2310  {
2311  if (!hasLocal)
2312  {
2313  nRemote++;
2314  }
2315  else
2316  {
2317  nMixed++;
2318  }
2319  }
2320  else if (hasLocal)
2321  {
2322  nLocal++;
2323  }
2324  }
2325  reduce(nLocal, sumOp<label>());
2326  reduce(nMixed, sumOp<label>());
2327  reduce(nRemote, sumOp<label>());
2328 
2329  Info<< "Overset analysis : nCells : "
2330  << returnReduce(cellTypes_.size(), sumOp<label>()) << nl
2331  << incrIndent
2332  << indent << "calculated : " << nCells[CALCULATED] << nl
2333  << indent << "interpolated : " << nCells[INTERPOLATED]
2334  << " (interpolated from local:" << nLocal
2335  << " mixed local/remote:" << nMixed
2336  << " remote:" << nRemote << ")" << nl
2337  << indent << "hole : " << nCells[HOLE] << nl
2338  << decrIndent << endl;
2339  }
2340 
2341  // Tbd: detect if anything changed. Most likely it did!
2342  return true;
2343 }
2344 
2345 
2346 // ************************************************************************* //
Foam::cellCellStencils::inverseDistance::~inverseDistance
virtual ~inverseDistance()
Destructor.
Definition: inverseDistanceCellCellStencil.C:1736
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
nZones
label nZones
Definition: interpolatedFaces.H:24
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1038
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Foam::treeBoundBox::overlaps
bool overlaps(const boundBox &bb) const
Overlaps other bounding box?
Definition: boundBoxI.H:221
Foam::val
label ListType::const_reference val
Definition: ListOps.H:407
inverseDistanceCellCellStencil.H
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::UPstream::commsTypes::nonBlocking
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::dynamicOversetFvMesh::correctBoundaryConditions
static void correctBoundaryConditions(typename GeoField::Boundary &bfld, const bool typeOnly)
Correct boundary conditions of certain type (typeOnly = true)
Definition: dynamicOversetFvMeshTemplates.C:117
Foam::PrimitivePatch::points
const Field< PointType > & points() const
Return reference to global points.
Definition: PrimitivePatch.H:300
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
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::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
Foam::OBJstream
OFstream that keeps track of vertices.
Definition: OBJstream.H:56
update
mesh update()
Foam::tmp< volScalarField >
Foam::fvMeshSubset
Given the original mesh and the list of selected cells, it creates the mesh consisting only of the de...
Definition: fvMeshSubset.H:73
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::cellCellStencils::inverseDistance::position
static point position(const boundBox &bb, const labelVector &nDivs, const label boxI)
Convert index back into coordinate.
Definition: inverseDistanceCellCellStencil.C:104
Foam::polyMesh::nGeometricD
label nGeometricD() const
Return the number of valid geometric dimensions in the mesh.
Definition: polyMesh.C:838
Foam::DynamicList< label >
fvMeshSubset.H
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::cellCellStencils::inverseDistance::stencilWeights
virtual void stencilWeights(const point &sample, const pointList &donorCcs, scalarList &weights) const
Calculate inverse distance weights for a single acceptor.
Definition: inverseDistanceCellCellStencil.C:1435
globalIndex.H
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:426
Foam::treeBoundBox
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:87
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:88
Foam::bitSet::any
bool any() const
True if any bits in this bitset are set.
Definition: bitSetI.H:460
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:563
dynamicOversetFvMesh.H
Foam::orEqOp
Definition: ops.H:86
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:182
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::boundBox::max
const point & max() const
Maximum describing the bounding box.
Definition: boundBoxI.H:97
meshBb
List< treeBoundBox > meshBb(1, treeBoundBox(boundBox(coarseMesh.points(), false)).extend(rndGen, 1e-3))
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::PstreamBuffers::clear
void clear()
Clear storage and reset.
Definition: PstreamBuffers.C:130
Foam::bitSet::test
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:512
Foam::incrIndent
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:314
syncTools.H
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::cellCellStencils::inverseDistance::index
static label index(const labelVector &nDivs, const labelVector &)
Convert ijk indices into single index.
Definition: inverseDistanceCellCellStencil.C:60
Foam::boundBox::min
const point & min() const
Minimum describing the bounding box.
Definition: boundBoxI.H:91
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
patchTypes
wordList patchTypes(nPatches)
Foam::fvBoundaryMesh
Foam::fvBoundaryMesh.
Definition: fvBoundaryMesh.H:57
Foam::labelVector
Vector< label > labelVector
Vector of labels.
Definition: labelVector.H:51
Foam::oversetFvPatchField::write
virtual void write(Ostream &os) const
Write.
Definition: oversetFvPatchField.C:222
Foam::boundBox::overlaps
bool overlaps(const boundBox &bb) const
Overlaps/touches boundingBox?
Definition: boundBoxI.H:221
Foam::boundBox::span
vector span() const
The bounding box span (from minimum to maximum)
Definition: boundBoxI.H:127
meshParts
PtrList< fvMeshSubset > meshParts(nZones)
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::cellCellStencils::inverseDistance::overlaps
static bool overlaps(const boundBox &bb, const labelVector &nDivs, const PackedList< 2 > &voxels, const treeBoundBox &subBb, const unsigned int val)
Is any voxel inside subBb set to val.
Definition: inverseDistanceCellCellStencil.C:271
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:258
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::label
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:62
Foam::Field< vector >
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::cellCellStencils::inverseDistance::cellBb
static treeBoundBox cellBb(const primitiveMesh &mesh, const label celli)
Calculate bounding box of cell.
Definition: inverseDistanceCellCellStencil.C:237
Foam::cellCellStencils::inverseDistance::walkFront
void walkFront(const scalar layerRelax, const labelListList &allStencil, labelList &allCellTypes, scalarField &allWeight) const
Surround holes with layer(s) of interpolated cells.
Definition: inverseDistanceCellCellStencil.C:1248
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:163
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:436
Foam::fvPatch
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:63
regionSplit.H
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:43
samples
scalarField samples(nIntervals, Zero)
Foam::regionSplit
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:140
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:65
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
Foam::regionSplit::nRegions
label nRegions() const
Return total number of regions.
Definition: regionSplit.H:253
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::cellCellStencils::inverseDistance::markBoundaries
static void markBoundaries(const fvMesh &mesh, const vector &smallVec, const boundBox &bb, const labelVector &nDivs, PackedList< 2 > &patchTypes, const labelList &cellMap, labelList &patchCellTypes)
Mark voxels of patchTypes with type of patch face.
Definition: inverseDistanceCellCellStencil.C:159
Foam::mapDistribute::distribute
void distribute(List< T > &fld, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Distribute data using default commsType.
Definition: mapDistributeTemplates.C:152
Foam::cellCellStencils::inverseDistance::fill
static void fill(PackedList< 2 > &elems, const boundBox &bb, const labelVector &nDivs, const boundBox &subBb, const unsigned int val)
Fill all elements overlapping subBb with value val.
Definition: inverseDistanceCellCellStencil.C:121
Foam::PstreamBuffers::finishedSends
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
Definition: PstreamBuffers.C:80
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::cellCellStencils::inverseDistance::createStencil
virtual void createStencil(const globalIndex &)
Create stencil starting from the donor containing the acceptor.
Definition: inverseDistanceCellCellStencil.C:1470
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::decrIndent
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:321
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::PtrList::set
const T * set(const label i) const
Return const pointer to element (if set) or nullptr.
Definition: PtrListI.H:143
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
Foam::indent
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:307
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::maxEqOp
Definition: ops.H:80
nCellsPerZone
labelList nCellsPerZone(nZones, Zero)
treeBoundBoxList.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::cellCellStencils::addToRunTimeSelectionTable
addToRunTimeSelectionTable(cellCellStencil, cellVolumeWeight, mesh)
Foam::cellCellStencils::inverseDistance::seedCell
void seedCell(const label cellI, const scalar wantedFraction, bitSet &isFront, scalarField &fraction) const
Seed faces of cell with wantedFraction (if higher than current)
Definition: inverseDistanceCellCellStencil.C:1227
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:444
Foam::cellCellStencils::inverseDistance::update
virtual bool update()
Update stencils. Return false if nothing changed.
Definition: inverseDistanceCellCellStencil.C:1742
Foam::Pstream::listCombineGather
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:290
nSamples
const label nSamples(pdfDictionary.get< label >("nSamples"))
Time.H
Foam::polyMesh::findCell
label findCell(const point &p, const cellDecomposition=CELL_TETS) const
Find cell enclosing this location and return index.
Definition: polyMesh.C:1453
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:176
Foam::linePointRef
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:47
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
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
cellTypes
const labelList & cellTypes
Definition: setCellMask.H:33
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:350
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::VectorSpace::max
static const Form max
Definition: VectorSpace.H:117
f
labelList f(nPoints)
Foam::cellCellStencil
Calculation of interpolation stencils.
Definition: cellCellStencil.H:61
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition: BitOps.H:74
Foam::GeometricField::boundaryFieldRef
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
Definition: GeometricField.C:752
Foam::Vector< label >
Foam::List< label >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::PackedList< 2 >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::start
label ListType::const_reference const label start
Definition: ListOps.H:408
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
Foam::UList< label >
points
const pointField & points
Definition: gmvOutputHeader.H:1
k
label k
Boltzmann constant.
Definition: LISASMDCalcMethod2.H:41
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::primitiveMesh::nPoints
label nPoints() const
Number of mesh points.
Definition: primitiveMeshI.H:37
Foam::IOList< label >
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:115
oversetFvPatch.H
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::direction
uint8_t direction
Definition: direction.H:47
Foam::cellCellStencils::inverseDistance::index3
static labelVector index3(const labelVector &nDivs, const label)
Convert single index into ijk.
Definition: inverseDistanceCellCellStencil.C:70
FUNCTION_NAME
#define FUNCTION_NAME
Definition: messageStream.H:261
Foam::roots::type
type
Types of root.
Definition: Roots.H:54
Foam::oversetFvPatchField
Boundary condition for use on overset patches. To be run in combination with special dynamicFvMesh ty...
Definition: oversetFvPatchField.H:56
Foam::fvPatch::faceCells
virtual const labelUList & faceCells() const
Return faceCells.
Definition: fvPatch.C:89
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
Foam::fvPatch::patch
const polyPatch & patch() const
Return the polyPatch.
Definition: fvPatch.H:145
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:109
Foam::cellCellStencils::inverseDistance::findHoles
void findHoles(const globalIndex &globalCells, const fvMesh &mesh, const labelList &zoneID, const labelListList &stencil, labelList &cellTypes) const
Do flood filling to detect unreachable (from patches) sections.
Definition: inverseDistanceCellCellStencil.C:945
Foam::cellCellStencils::inverseDistance::markDonors
void markDonors(const globalIndex &globalCells, PstreamBuffers &pBufs, const PtrList< fvMeshSubset > &meshParts, const List< treeBoundBoxList > &meshBb, const labelList &allCellTypes, const label srcI, const label tgtI, labelListList &allStencil, labelList &allDonor) const
Determine donors for all tgt cells.
Definition: inverseDistanceCellCellStencil.C:483
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
Foam::cellCellStencils::defineTypeNameAndDebug
defineTypeNameAndDebug(cellVolumeWeight, 0)
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::plusEqOp
Definition: ops.H:72
Foam::PATCH
PDRpatchDef PATCH
Definition: PDRpatchDef.H:112
Foam::UIPstream
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:56
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:432
Foam::cbrt
dimensionedScalar cbrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:155
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::GeometricField< scalar, fvPatchField, volMesh >
Foam::cellCellStencils::inverseDistance::betterDonor
bool betterDonor(const label destMesh, const label currentDonorMesh, const label newDonorMesh) const
If multiple donors meshes: decide which is best.
Definition: inverseDistanceCellCellStencil.C:441
Foam::treeBoundBoxList
List< treeBoundBox > treeBoundBoxList
List of bounding boxes.
Definition: treeBoundBoxList.H:46
Foam::minMagSqrEqOp
Definition: ops.H:82
Foam::orOp
Definition: ops.H:234
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
zeroGradientFvPatchFields.H
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
OBJstream.H
waveMethod.H
Foam::bitSet::transfer
void transfer(bitSet &bitset)
Definition: bitSetI.H:530
Foam::cellCellStencils::inverseDistance::markPatchesAsHoles
void markPatchesAsHoles(PstreamBuffers &pBufs, const PtrList< fvMeshSubset > &meshParts, const List< treeBoundBoxList > &patchBb, const List< labelVector > &patchDivisions, const PtrList< PackedList< 2 >> &patchParts, const label srcI, const label tgtI, labelList &allCellTypes) const
Mark all cells overlapping (a voxel covered by) a src patch.
Definition: inverseDistanceCellCellStencil.C:315
Foam::globalIndex::toGlobal
label toGlobal(const label i) const
From local to global index.
Definition: globalIndexI.H:164
Foam::flipOp
Functor to negate primitives. Dummy for most other types.
Definition: flipOp.H:53
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:59
Foam::polyMesh::tetBasePtIs
const labelIOList & tetBasePtIs() const
Return the tetBasePtIs.
Definition: polyMesh.C:861
Foam::primitiveMesh
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:78