immersedBoundaryFvPatch.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | foam-extend: Open Source CFD
4  \\ / O peration | Version: 3.2
5  \\ / A nd | Web: http://www.foam-extend.org
6  \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9  This file is part of foam-extend.
10 
11  foam-extend is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation, either version 3 of the License, or (at your
14  option) any later version.
15 
16  foam-extend is distributed in the hope that it will be useful, but
17  WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
27 #include "foamTime.H"
28 #include "fvBoundaryMesh.H"
29 #include "fvMesh.H"
30 #include "SortableList.H"
31 #include "volFields.H"
32 #include "surfaceFields.H"
34 
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39  defineTypeNameAndDebug(immersedBoundaryFvPatch, 0);
40 
41  addToRunTimeSelectionTable(fvPatch, immersedBoundaryFvPatch, polyPatch);
42 }
43 
44 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 
46 const Foam::debug::tolerancesSwitch
48 (
49  "immersedBoundaryRadiusFactor",
50  3.5
51 // 5
52 );
53 
54 
55 const Foam::debug::tolerancesSwitch
57 (
58  "immersedBoundaryAngleFactor",
59  80
60 // 170
61 );
62 
63 
66 (
67  "immersedBoundaryMaxCellCellRows",
68  4
69 // 5
70 );
71 
72 
73 const Foam::debug::tolerancesSwitch
75 (
76  "immersedBoundaryDistFactor",
77  1.5
78 );
79 
80 
81 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
82 
84 {
85  if (debug)
86  {
87  InfoIn("void immersedBoundaryFvPatch::makeGamma() const")
88  << "creating fluid cells indicator "
89  << "for immersed boundary" << name()
90  << endl;
91  }
92 
93  // It is an error to attempt to recalculate
94  // if the pointer is already set
95  if (gammaPtr_)
96  {
97  FatalErrorIn("immersedBoundaryFvPatch::makeGamma() const")
98  << "fluid cells indicator already exist"
99  << "for immersed boundary" << name()
100  << abort(FatalError);
101  }
102 
103  gammaPtr_ =
104  new volScalarField
105  (
106  IOobject
107  (
108  "ibGamma" + name(),
109  mesh_.time().timeName(),
110  mesh_,
113  ),
114  mesh_,
115  dimensionedScalar("1", dimless, 1)
116  );
117 
118  scalarField& gammaI = gammaPtr_->internalField();
119 
120  // Start from gammaExt and mark IB cells and inactive
121  gammaI = gammaExt().internalField();
122 
123  const labelList& ibc = ibCells();
124 
125  forAll (ibc, cellI)
126  {
127  gammaI[ibc[cellI]] = 0.0;
128  }
129 
130  // Not allowed to call correctBoundaryConditions. HJ, 16/Apr/2012
131  // Evaluate coupled boundaries and copy out the uncoupled ones
132  gammaPtr_->boundaryField().evaluateCoupled();
133 
134  forAll (gammaPtr_->boundaryField(), patchI)
135  {
136  if (!gammaPtr_->boundaryField()[patchI].coupled())
137  {
138  gammaPtr_->boundaryField()[patchI] =
139  gammaPtr_->boundaryField()[patchI].patchInternalField();
140  }
141  }
142 }
143 
144 
146 {
147  if (debug)
148  {
149  InfoIn("void immersedBoundaryFvPatch::makeGammaExt() const")
150  << "creating extended fluid cells indicator "
151  << "for immersed boundary " << name()
152  << endl;
153  }
154 
155  // It is an error to attempt to recalculate
156  // if the pointer is already set
157  if (gammaExtPtr_)
158  {
159  FatalErrorIn("immersedBoundaryFvPatch::makeGammaExt() const")
160  << "extended fluid cells indicator already exist "
161  << "for immersed boundary " << name()
162  << abort(FatalError);
163  }
164 
165  gammaExtPtr_ =
166  new volScalarField
167  (
168  IOobject
169  (
170  "ibGammaExt" + name(),
171  mesh_.time().timeName(),
172  mesh_,
175  ),
176  mesh_,
177  dimensionedScalar("1", dimless, 1)
178  );
179 
180  scalarField& gammaExtI = gammaExtPtr_->internalField();
181 
182  const vectorField& C = mesh_.cellCentres();
183 
184  // Mark cells that are inside or outside of the triangular surface
185  boolList inside = ibPolyPatch_.triSurfSearch().calcInside(C);
186 
187  // Adjust selection of cells: inside or outside of immersed boundary
188  if (internalFlow())
189  {
190  Info<< "Internal flow" << endl;
191  forAll (gammaExtI, cellI)
192  {
193  if (!inside[cellI])
194  {
195  gammaExtI[cellI] = 0;
196  }
197  }
198  }
199  else
200  {
201  Info<< "External flow" << endl;
202  forAll (gammaExtI, cellI)
203  {
204  if (inside[cellI])
205  {
206  gammaExtI[cellI] = 0;
207  }
208  }
209  }
210 
211  // Not allowed to call correctBoundaryConditions. HJ, 16/Apr/2012
212  // Evaluate coupled boundaries and copy out the uncoupled ones
213  gammaExtPtr_->boundaryField().evaluateCoupled();
214 }
215 
216 
218 {
219  if (debug)
220  {
221  InfoIn("void immersedBoundaryFvPatch::makeSGamma() const")
222  << "creating fluid faces indicator "
223  << "for immersed boundary " << name()
224  << endl;
225  }
226 
227  // It is an error to attempt to recalculate
228  // if the pointer is already set
229  if (sGammaPtr_)
230  {
231  FatalErrorIn("immersedBoundaryFvPatch::makeSGamma() const")
232  << "fluid faces indicator already exist "
233  << "for immersed boundary " << name()
234  << abort(FatalError);
235  }
236 
237  // Note: change in algorithm
238  // 1) First, mark all faces as dead
239  // 2) Mark faces as live if they are between two live cells
240  sGammaPtr_ =
242  (
243  IOobject
244  (
245  "sGamma" + name(),
246  mesh_.time().timeName(),
247  mesh_,
250  ),
251  mesh_,
252  dimensionedScalar("zero", dimless, 0),
253  calculatedFvsPatchScalarField::typeName
254  );
255 
256  // Get access to components of sGamma
257  scalarField& sGammaI = sGammaPtr_->internalField();
258 
260  sGammaPtr_->boundaryField();
261 
262  const unallocLabelList& owner = mesh_.owner();
263  const unallocLabelList& neighbour = mesh_.neighbour();
264 
265  // Live cells indicator
266  const volScalarField& g = gamma();
267 
268  // Extended live cells indicator
269  const volScalarField& gExt = gammaExt();
270  const scalarField& gExtIn = gExt.internalField();
271 
272  const volScalarField::GeometricBoundaryField& gExtPatches =
273  gExt.boundaryField();
274 
275  volScalarField gIb = gExt - g;
276  const scalarField& gIbIn = gIb.internalField();
277 
278  const volScalarField::GeometricBoundaryField& gIbPatches =
279  gIb.boundaryField();
280 
281  // Internal faces: flux is live between all active and IB cells
282  forAll (sGammaI, faceI)
283  {
284  // If both cells are live, flux is live
285  if
286  (
287  gExtIn[owner[faceI]] > SMALL
288  && gExtIn[neighbour[faceI]] > SMALL
289  )
290  {
291  sGammaI[faceI] = 1;
292  }
293  }
294 
295  // Kill fluxes between two IB cells
296  forAll (sGammaI, faceI)
297  {
298  // If both cells are live, flux is live
299  if
300  (
301  gIbIn[owner[faceI]] > SMALL
302  && gIbIn[neighbour[faceI]] > SMALL
303  )
304  {
305  sGammaI[faceI] = 0;
306  }
307  }
308 
309  forAll (gExtPatches, patchI)
310  {
311  if (gExtPatches[patchI].coupled())
312  {
313  scalarField& gP = sGammaPatches[patchI];
314 
315  // For coupled patches, check gammaExt
316  scalarField gammaOwn = gExtPatches[patchI].patchInternalField();
317 
318  scalarField gammaNei = gExtPatches[patchI].patchNeighbourField();
319 
320  forAll (gammaOwn, faceI)
321  {
322  if
323  (
324  gammaOwn[faceI] > SMALL
325  && gammaNei[faceI] > SMALL
326  )
327  {
328  gP[faceI] = 1;
329  }
330  }
331 
332  // For coupled patches, kill IB
333  scalarField gammaIbOwn = gIbPatches[patchI].patchInternalField();
334 
335  scalarField gammaIbNei = gIbPatches[patchI].patchNeighbourField();
336 
337  forAll (gammaOwn, faceI)
338  {
339  if
340  (
341  gammaIbOwn[faceI] > SMALL
342  && gammaIbNei[faceI] > SMALL
343  )
344  {
345  gP[faceI] = 0;
346  }
347  }
348  }
349  else
350  {
351  // For regular patches, check live cells only to achieve
352  // correct global mass adjustment.
353  // HJ, 21/May/2012
354  scalarField gammaFc =
355  g.boundaryField()[patchI].patchInternalField();
356 
357  scalarField& gP = sGammaPatches[patchI];
358 
359  forAll (gammaFc, faceI)
360  {
361  if (gammaFc[faceI] > SMALL)
362  {
363  gP[faceI] = 1;
364  }
365  }
366  }
367  }
368 }
369 
370 
372 {
373  if (debug)
374  {
375  InfoIn("void immersedBoundaryFvPatch::makeIbCells() const")
376  << "create list of cells next to immersed boundary "
377  << "for immersed boundary " << name()
378  << endl;
379  }
380 
381  // It is an error to attempt to recalculate
382  // if the pointer is already set
383  if (ibCellsPtr_)
384  {
385  FatalErrorIn("immersedBoundaryFvPatch::makeIbCells() const")
386  << "list of cells next to immersed boundary already exist "
387  << "for immersed boundary " << name()
388  << abort(FatalError);
389  }
390 
391  labelHashSet ibCellSet;
392 
393  const unallocLabelList& owner = mesh_.owner();
394  const unallocLabelList& neighbour = mesh_.neighbour();
395 
396  const volScalarField gE = gammaExt();
397  const scalarField& gammaExtI = gE.internalField();
398 
399  forAll (neighbour, faceI)
400  {
401  if (mag(gammaExtI[neighbour[faceI]] - gammaExtI[owner[faceI]]) > SMALL)
402  {
403  if (gammaExtI[owner[faceI]] > SMALL)
404  {
405  if (!ibCellSet.found(owner[faceI]))
406  {
407  ibCellSet.insert(owner[faceI]);
408  }
409  }
410  else
411  {
412  if (!ibCellSet.found(neighbour[faceI]))
413  {
414  ibCellSet.insert(neighbour[faceI]);
415  }
416  }
417  }
418  }
419 
420  forAll (gE.boundaryField(), patchI)
421  {
422  if (gE.boundaryField()[patchI].coupled())
423  {
424  scalarField gammaExtOwn =
425  gE.boundaryField()[patchI].patchInternalField();
426 
427  scalarField gammaExtNei =
428  gE.boundaryField()[patchI].patchNeighbourField();
429 
430  const unallocLabelList& fCells =
431  mesh_.boundary()[patchI].faceCells();
432 
433  forAll (gammaExtOwn, faceI)
434  {
435  if
436  (
437  mag(gammaExtNei[faceI] - gammaExtOwn[faceI])
438  > SMALL
439  )
440  {
441  if (gammaExtOwn[faceI] > SMALL)
442  {
443  if (!ibCellSet.found(fCells[faceI]))
444  {
445  ibCellSet.insert(fCells[faceI]);
446  }
447  }
448  else if (2*gammaExtOwn.size() == fCells.size())
449  {
450  if
451  (
452  !ibCellSet.found
453  (
454  fCells[gammaExtOwn.size() + faceI]
455  )
456  )
457  {
458  ibCellSet.insert
459  (
460  fCells[gammaExtOwn.size() + faceI]
461  );
462  }
463  }
464  }
465  }
466  }
467  }
468 
469  ibCellsPtr_ = new labelList(ibCellSet.toc());
470  sort(*ibCellsPtr_);
471 
472  Pout << "Number of IB cells: " << ibCellsPtr_->size() << endl;
473 }
474 
475 
477 {
478  if (debug)
479  {
480  InfoIn("void immersedBoundaryFvPatch::addIbCornerCells() const")
481  << "add cells next to sharp corner "
482  << "for immersed boundary " << name()
483  << endl;
484  }
485 
486  const vectorField& C = mesh_.cellCentres();
487  const vectorField& Cf = mesh_.faceCentres();
488  const vectorField& Sf = mesh_.faceAreas();
489 
490  const cellList& meshCells = mesh_.cells();
491  const unallocLabelList& own = mesh_.owner();
492  const unallocLabelList& nei = mesh_.neighbour();
493 
494  label nCornerCells = 0;
495  labelList cornerCells;
496 
497  const triSurfaceSearch& tss = ibPolyPatch_.triSurfSearch();
498 
499  do
500  {
501  // Access to derived data from do-loop: this will be re-calculated
502  // HJ, 21/May/2012
503  const labelList& ibc = ibCells();
504 
505  // Note: the algorithm is originally written with inward-facing normals
506  // and subsequently changed: IB surface normals point outwards
507  // HJ, 21/May/2012
508  const vectorField& ibn = ibNormals();
509 
510  const scalarField& gammaI = gamma().internalField();
511 
512  labelHashSet cornerIbCellSet;
513 
514  const labelList& ibf = ibFaces();
515 
516  forAll (ibf, faceI)
517  {
518  const label& ownCell = own[ibf[faceI]];
519  const label& neiCell = nei[ibf[faceI]];
520 
521 // label ibCell = -1;
522  label liveCell = -1;
523 
524  if (gammaI[ownCell] > SMALL)
525  {
526 // ibCell = neiCell;
527  liveCell = ownCell;
528  }
529  else
530  {
531 // ibCell = ownCell;
532  liveCell = neiCell;
533  }
534 
535  scalar delta = cellSize(liveCell);
536  vector span(2*delta, 2*delta, 2*delta);
537 
538  pointIndexHit pih = tss.nearest(C[liveCell], span);
539 
540  if (pih.hit())
541  {
542  vector n =
544  (
545  ibPolyPatch_.ibMesh(),
546  pih.index(),
547  pih.hitPoint()
548  );
549 
550  scalar totalArea = 0;
551  {
552  const labelList& cellFaces = meshCells[liveCell];
553 
554  forAll (cellFaces, faceI)
555  {
556  label curFace = cellFaces[faceI];
557 
558  vector curSf = Sf[curFace];
559 
560  if ((curSf & (Cf[curFace] - C[liveCell])) < 0)
561  {
562  curSf *= -1;
563  }
564 
565  if ((curSf & n) > 0)
566  {
567  totalArea += (curSf & n);
568  }
569  }
570  }
571 
572  scalar area = 0;
573  {
574  const labelList& cellFaces = meshCells[liveCell];
575 
576  forAll (cellFaces, faceI)
577  {
578  label curFace = cellFaces[faceI];
579 
580  vector curSf = Sf[curFace];
581 
582  label neiCell = -1;
583 
584  //HJ bug fix?
585  if (mesh_.isInternalFace(curFace))
586  {
587  if (own[curFace] == liveCell)
588  {
589  neiCell = nei[curFace];
590  }
591  else
592  {
593  neiCell = own[curFace];
594  }
595  }
596 
597  label ibCell = findIndex(ibc, neiCell);
598 
599  if (ibCell != -1)
600  {
601  // Note that ibn points outwards
602  if ((-ibn[ibCell] & n) > 0)
603  {
604  area += mag(curSf & n);
605  }
606  }
607  }
608  }
609 
610  if (area/totalArea < 0.5)
611  {
612  if (!cornerIbCellSet.found(liveCell))
613  {
614  cornerIbCellSet.insert(liveCell);
615  }
616  }
617  }
618  }
619 
620  cornerCells = cornerIbCellSet.toc();
621  ibCellsPtr_->append(cornerCells);
622  nCornerCells += cornerCells.size();
623 
624  deleteDemandDrivenData(gammaPtr_);
625 
626  deleteDemandDrivenData(ibFacesPtr_);
627  deleteDemandDrivenData(ibFaceCellsPtr_);
628  deleteDemandDrivenData(ibFaceFlipsPtr_);
629 
630  deleteDemandDrivenData(ibPointsPtr_);
631  deleteDemandDrivenData(ibNormalsPtr_);
632  deleteDemandDrivenData(hitFacesPtr_);
633  deleteDemandDrivenData(ibSamplingPointsPtr_);
634 
635  deleteDemandDrivenData(ibSamplingWeightsPtr_);
636  deleteDemandDrivenData(ibSamplingProcWeightsPtr_);
637  }
638  while (cornerCells.size() > 0);
639 }
640 
641 
643 {
644  if (debug)
645  {
646  InfoIn("void immersedBoundaryFvPatch::makeIbFaces() const")
647  << "create list of faces next to immersed boundary "
648  << "for immersed boundary " << name()
649  << endl;
650  }
651 
652  // It is an error to attempt to recalculate
653  // if the pointer is already set
654  if (ibFacesPtr_ || ibFaceCellsPtr_ || ibFaceFlipsPtr_)
655  {
656  FatalErrorIn("immersedBoundaryFvPatch::makeIbFaces() const")
657  << "list of faces next to immersed boundary already exist "
658  << "for immersed boundary " << name()
659  << abort(FatalError);
660  }
661 
662  // Mark IB cells with their index
663  const labelList& ibc = ibCells();
664 
665  labelList ibCellIndicator(mesh_.nCells(), -1);
666 
667  forAll (ibc, ibcI)
668  {
669  ibCellIndicator[ibc[ibcI]] = ibcI;
670  }
671 
672  dynamicLabelList ibF(2*ibc.size());
673  dynamicLabelList ibFC(2*ibc.size());
674  DynamicList<bool> ibFF(2*ibc.size());
675 
676  const unallocLabelList& owner = mesh_.owner();
677  const unallocLabelList& neighbour = mesh_.neighbour();
678 
679 // const scalarField& gammaI = gamma().internalField();
680 
681  forAll (neighbour, faceI)
682  {
683  // Old check done using mag gamma. Changed for internal cells
684  if
685  (
686  ibCellIndicator[owner[faceI]] == -1
687  && ibCellIndicator[neighbour[faceI]] > -1
688  )
689  {
690  // Owner is live, neighbour IB. Its IB index is in
691  // ibCellIndicator
692  ibF.append(faceI);
693  ibFC.append(ibCellIndicator[neighbour[faceI]]);
694  ibFF.append(false);
695  }
696  else if
697  (
698  ibCellIndicator[owner[faceI]] > -1
699  && ibCellIndicator[neighbour[faceI]] == -1
700  )
701  {
702  // Neighbour is live, owner IB. Its IB index is in
703  // ibCellIndicator
704  ibF.append(faceI);
705  ibFC.append(ibCellIndicator[owner[faceI]]);
706  ibFF.append(true);
707  }
708  }
709 
710  const volScalarField::GeometricBoundaryField& gammaPatches =
711  gamma().boundaryField();
712 
713  forAll (gammaPatches, patchI)
714  {
715  // Note: take faceCells from fvPatch (because of empty)
716  const labelList& fc = mesh_.boundary()[patchI].faceCells();
717  const label start = mesh_.boundaryMesh()[patchI].start();
718 
719  if (gammaPatches[patchI].coupled())
720  {
721  scalarField gammaOwn =
722  gammaPatches[patchI].patchInternalField();
723 
724  scalarField gammaNei =
725  gammaPatches[patchI].patchNeighbourField();
726 
727  forAll (gammaOwn, patchFaceI)
728  {
729  if
730  (
731  mag(gammaNei[patchFaceI] - gammaOwn[patchFaceI]) > SMALL
732  )
733  {
734  if (ibCellIndicator[fc[patchFaceI]] > -1)
735  {
736  // Owner cell is IB
737  ibF.append(start + patchFaceI);
738  ibFC.append(ibCellIndicator[fc[patchFaceI]]);
739  ibFF.append(false);
740  }
741  else
742  {
743  // Neighbour cell is IB
744  ibF.append(start + patchFaceI);
745  ibFC.append(-1);
746  ibFF.append(true);
747  }
748  }
749  }
750  }
751  }
752 
753  // Pack the data
754  ibF.shrink();
755  ibFC.shrink();
756  ibFF.shrink();
757 
758  ibFacesPtr_ = new labelList(ibF.xfer());
759 
760  ibFaceCellsPtr_ = new labelList(ibFC.xfer());
761  ibFaceFlipsPtr_ = new boolList(ibFF.xfer());
762 }
763 
764 
766 {
767  if (debug)
768  {
769  InfoIn("void immersedBoundaryFvPatch::makeIbInsideFaces() const")
770  << "create list of faces next to immersed boundary "
771  << "for immersed boundary " << name()
772  << endl;
773  }
774 
775  // It is an error to attempt to recalculate
776  // if the pointer is already set
777  if (ibInsideFacesPtr_)
778  {
779  FatalErrorIn("immersedBoundaryFvPatch::makeIbInsideFaces() const")
780  << "list of faces next to immersed boundary already exist "
781  << "for immersed boundary " << name()
782  << abort(FatalError);
783  }
784 
785  labelHashSet ibInsideFSet;
786 
787  const labelList& owner = mesh_.faceOwner();
788  const labelList& neighbour = mesh_.faceNeighbour();
789 
790  const volScalarField gE = gammaExt();
791  const scalarField& gammaExtI = gE.internalField();
792 
793  forAll (neighbour, faceI)
794  {
795  if (mag(gammaExtI[neighbour[faceI]] - gammaExtI[owner[faceI]]) > SMALL)
796  {
797  ibInsideFSet.insert(faceI);
798  }
799  }
800 
801  forAll (gE.boundaryField(), patchI)
802  {
803  if (gE.boundaryField()[patchI].coupled())
804  {
805  scalarField gammaOwn =
806  gE.boundaryField()[patchI].patchInternalField();
807 
808  scalarField gammaNei =
809  gE.boundaryField()[patchI].patchNeighbourField();
810 
811  label size = mesh_.boundaryMesh()[patchI].size();
812  label start = mesh_.boundaryMesh()[patchI].start();
813 
814  forAll (gammaOwn, faceI)
815  {
816  if
817  (
818  mag(gammaNei[faceI] - gammaOwn[faceI]) > SMALL
819  )
820  {
821  if (!ibInsideFSet.found(start + faceI))
822  {
823  ibInsideFSet.insert(start + faceI);
824  }
825 
826  if (2*gammaOwn.size() == size)
827  {
828  if
829  (
830  !ibInsideFSet.found
831  (
832  start + size/2 + faceI
833  )
834  )
835  {
836  ibInsideFSet.insert
837  (
838  start + size/2 + faceI
839  );
840  }
841  }
842  }
843  }
844  }
845  }
846 
847  ibInsideFacesPtr_ = new labelList(ibInsideFSet.toc());
848  sort(*ibInsideFacesPtr_);
849 }
850 
851 
853 {
854  if (debug)
855  {
856  InfoIn("void immersedBoundaryFvPatch::makeIbInternalFaces() const")
857  << "create list of faces next to immersed boundary"
858  << endl;
859  }
860 
861  // It is an error to attempt to recalculate
862  // if the pointer is already set
863  if (ibInternalFacesPtr_)
864  {
865  FatalErrorIn("immersedBoundaryFvPatch::makeIbInternalFaces() const")
866  << "list of faces next to immersed boundary already exist"
867  << abort(FatalError);
868  }
869 
870  labelHashSet ibInternalFacesSet;
871 
872  const labelList& owner = mesh_.faceOwner();
873  const labelList& neighbour = mesh_.faceNeighbour();
874 
875  volScalarField gammaTmp
876  (
877  "gammaTmp",
878  gammaExt() - gamma()
879  );
880  const scalarField& gammaTmpI = gammaTmp.internalField();
881 
882  forAll (neighbour, faceI)
883  {
884  if
885  (
886  (gammaTmpI[neighbour[faceI]] > SMALL)
887  && (gammaTmpI[owner[faceI]] > SMALL)
888  )
889  {
890  ibInternalFacesSet.insert(faceI);
891  }
892  }
893 
894  forAll (gammaTmp.boundaryField(), patchI)
895  {
896  if (gammaTmp.boundaryField()[patchI].coupled())
897  {
898  scalarField gammaOwn =
899  gammaTmp.boundaryField()[patchI].patchInternalField();
900 
901  scalarField gammaNei =
902  gammaTmp.boundaryField()[patchI].patchNeighbourField();
903 
904  label size = mesh_.boundaryMesh()[patchI].size();
905  label start = mesh_.boundaryMesh()[patchI].start();
906 
907  forAll (gammaOwn, faceI)
908  {
909  if
910  (
911  (gammaNei[faceI] > SMALL)
912  && (gammaOwn[faceI] > SMALL)
913  )
914  {
915  if (!ibInternalFacesSet.found(start + faceI))
916  {
917  ibInternalFacesSet.insert(start + faceI);
918  }
919 
920  if (2*gammaOwn.size() == size)
921  {
922  if
923  (
924  !ibInternalFacesSet.found
925  (
926  start + size/2 + faceI
927  )
928  )
929  {
930  ibInternalFacesSet.insert
931  (
932  start + size/2 + faceI
933  );
934  }
935  }
936  }
937  }
938  }
939  }
940 
941  ibInternalFacesPtr_ = new labelList(ibInternalFacesSet.toc());
942  sort(*ibInternalFacesPtr_);
943 }
944 
945 
947 {
948  if (debug)
949  {
950  InfoIn
951  (
952  "void immersedBoundaryFvPatch::makeIbPointsAndNormals() const"
953  ) << "create immersed boundary points and normals "
954  << "for immersed boundary " << name()
955  << endl;
956  }
957 
958  // It is an error to attempt to recalculate
959  // if the pointer is already set
960  if (ibPointsPtr_ || ibNormalsPtr_ || hitFacesPtr_ || ibSamplingPointsPtr_)
961  {
963  (
964  "immersedBoundaryFvPatch::makeIbPointsAndNormals() const"
965  )
966  << "immersed boundary points and normals already exist"
967  << "for immersed boundary " << name()
968  << abort(FatalError);
969  }
970 
971  // Find average cell dimension
972  const labelList& ibc = ibCells();
973 
974  scalarField delta(ibc.size(), 0.0);
975 
976  forAll (delta, cellI)
977  {
978  delta[cellI] = cellSize(ibc[cellI]);
979  }
980 
981  // Find nearest triSurface point for each interface cell centre
982  ibPointsPtr_ = new vectorField(ibc.size(), vector::zero);
983  ibNormalsPtr_ = new vectorField(ibc.size(), vector::zero);
984  hitFacesPtr_ = new labelList(ibc.size(), -1);
985  ibSamplingPointsPtr_ = new vectorField(ibc.size(), vector::zero);
986 
987  vectorField& ibPoints = *ibPointsPtr_;
988  vectorField& ibNormals = *ibNormalsPtr_;
989  labelList& ibHitFaces = *hitFacesPtr_;
990  vectorField& ibSamplingPoints = *ibSamplingPointsPtr_;
991 
992  const vectorField& C = mesh_.C().internalField();
993 
994  // Get IB cell centres
995  vectorField ibCellCentres(C, ibc);
996 
997  const triSurfaceSearch& tss = ibPolyPatch_.triSurfSearch();
998 
999  forAll (ibc, cellI)
1000  {
1001  // Adjust search span if needed. HJ, 14/Dec/2012
1002  vector span
1003  (
1004  2*radiusFactor_()*delta[cellI],
1005  2*radiusFactor_()*delta[cellI],
1006  2*radiusFactor_()*delta[cellI]
1007  );
1008 
1009  pointIndexHit pih = tss.nearest(ibCellCentres[cellI], span);
1010 
1011  if (pih.hit())
1012  {
1013  ibPoints[cellI] = pih.hitPoint();
1014  ibNormals[cellI] =
1016  (
1017  ibPolyPatch_.ibMesh(),
1018  pih.index(),
1019  pih.hitPoint()
1020  );
1021 
1022  // Note: ibNormals point OUT of the domain
1023  if (!internalFlow())
1024  {
1025  ibNormals[cellI] *= -1;
1026  }
1027 
1028  ibHitFaces[cellI] = pih.index();
1029  }
1030  else
1031  {
1032  FatalErrorIn
1033  (
1034  "immersedBoundaryFvPatch::makeIbPointsAndNormals() const"
1035  ) << "Can't find nearest triSurface point for cell "
1036  << ibc[cellI] << ", "
1037  << mesh_.cellCentres()[ibc[cellI]]
1038  << "Hit data = " << pih << nl
1039  << abort(FatalError);
1040  }
1041 
1042  if
1043  (
1044  mesh_.nGeometricD() < 3
1045  && mag(ibCellCentres[cellI].z() - ibPoints[cellI].z()) > SMALL
1046  )
1047  {
1048  WarningIn
1049  (
1050  "immersedBoundaryFvPatch::makeIbPointsAndNormals() const"
1051  ) << "Intersection point is not on symmetry plane " << nl
1052  << "C = " << ibCellCentres[cellI]
1053  << " D = " << ibPoints[cellI] << nl
1054  << "for 2-D geometry. Adjusting" << endl;
1055 
1056  ibPoints[cellI].z() = ibCellCentres[cellI].z();
1057  }
1058  }
1059 
1060  // Calculate sampling points locations
1061  ibSamplingPoints = ibPoints + distFactor_()*(ibCellCentres - ibPoints);
1062 }
1063 
1064 
1066 {
1067  if (debug)
1068  {
1069  InfoIn("void immersedBoundaryFvPatch::makeIbCellCells() const")
1070  << "create neighbour cells for ib cells"
1071  << endl;
1072  }
1073 
1074  // It is an error to attempt to recalculate
1075  // if the pointer is already set
1076  if
1077  (
1078  ibCellCellsPtr_
1079  || ibProcCentresPtr_
1080  || ibProcGammaPtr_
1081  || ibCellProcCellsPtr_
1082  )
1083  {
1084  FatalErrorIn
1085  (
1086  "immersedBoundaryFvPatch::makeIbCellCells() const"
1087  ) << "cell-cell addressing already exists"
1088  << abort(FatalError);
1089  }
1090 
1091  const labelList& ibc = ibCells();
1092 
1093  ibCellCellsPtr_ = new labelListList(ibc.size());
1094  labelListList& cellCells = *ibCellCellsPtr_;
1095 
1096  ibProcCentresPtr_ = new FieldField<Field, vector>(Pstream::nProcs());
1097  FieldField<Field, vector>& procCentres = *ibProcCentresPtr_;
1098 
1099  forAll (procCentres, procI)
1100  {
1101  procCentres.set(procI, new vectorField(0));
1102  }
1103 
1104  ibProcGammaPtr_ = new FieldField<Field, scalar>(Pstream::nProcs());
1105  FieldField<Field, scalar>& procGamma = *ibProcGammaPtr_;
1106 
1107  forAll (procGamma, procI)
1108  {
1109  procGamma.set(procI, new scalarField(0));
1110  }
1111 
1112 
1113  ibCellProcCellsPtr_ = new List<List<labelPair> >(ibc.size());
1114  List<List<labelPair> >& cellProcCells = *ibCellProcCellsPtr_;
1115 
1116  const cellList& meshCells = mesh_.cells();
1117 
1118  // In geometry initialisation, fields are not available: use raw mesh data
1119  // HJ after ZT, 6/Dec/2012
1120  const vectorField& C = mesh_.cellCentres();
1121 
1122  scalarField rM(ibCellSizes());
1123  rM *= radiusFactor_();
1124 
1125  const vectorField& ibp = ibPoints();
1126 
1127  // Note: the algorithm is originally written with inward-facing normals
1128  // and subsequently changed: IB surface normals point outwards
1129  // HJ, 21/May/2012
1130 // const vectorField& ibn = ibNormals();
1131 
1132  forAll (cellCells, cellI)
1133  {
1134  labelList curCells;
1135 
1136  findCellCells
1137  (
1138  C[ibc[cellI]],
1139  ibc[cellI],
1140  curCells
1141  );
1142 
1143  cellCells[cellI] = labelList(curCells.size(), -1);
1144 
1145  label cI = 0;
1146 
1147  for (label i = 0; i < curCells.size(); i++)
1148  {
1149  label curCell = curCells[i];
1150  scalar r = mag(C[curCell] - C[ibc[cellI]]);
1151 
1152  // Collect the cells within rM of the fitting cell
1153  if (r <= rM[cellI])
1154  {
1155 // scalar angleLimit =
1156 // -Foam::cos(angleFactor_()*mathematicalConstant::pi/180);
1157 
1158  vector dir = (C[curCell] - ibp[cellI]);
1159  dir /= mag(dir) + SMALL;
1160 
1161  // Change of sign of normal. HJ, 21/May/2012
1162 // if ((-ibn[cellI] & dir) >= angleLimit)
1163  {
1164  cellCells[cellI][cI++] = curCell;
1165  }
1166  }
1167  }
1168 
1169  cellCells[cellI].setSize(cI);
1170  }
1171 
1172  if (Pstream::parRun())
1173  {
1174  // Find immersed boundary cells next to processor boundaries
1175  labelHashSet procIbCellsSet;
1176 
1177  forAll (ibc, cellI)
1178  {
1179  const labelList& curCellCells = cellCells[cellI];
1180 
1181  if (curCellCells.size())
1182  {
1183  forAll (curCellCells, cI)
1184  {
1185  const labelList& faces = meshCells[curCellCells[cI]];
1186 
1187  bool foundProcessorFace = false;
1188 
1189  forAll (faces, faceI)
1190  {
1191  label patchID =
1192  mesh_.boundaryMesh().whichPatch(faces[faceI]);
1193 
1194  if (patchID != -1)
1195  {
1196  if
1197  (
1198  isA<processorPolyPatch>
1199  (
1200  mesh_.boundaryMesh()[patchID]
1201  )
1202  )
1203  {
1204  foundProcessorFace = true;
1205  }
1206  }
1207  }
1208 
1209  if (foundProcessorFace)
1210  {
1211  procIbCellsSet.insert(cellI);
1212  break;
1213  }
1214  }
1215  }
1216  else
1217  {
1218  const labelList& faces = meshCells[ibc[cellI]];
1219 
1220  bool foundProcessorFace = false;
1221 
1222  forAll (faces, faceI)
1223  {
1224  label patchID =
1225  mesh_.boundaryMesh().whichPatch(faces[faceI]);
1226 
1227  if (patchID != -1)
1228  {
1229  if
1230  (
1231  isA<processorPolyPatch>
1232  (
1233  mesh_.boundaryMesh()[patchID]
1234  )
1235  )
1236  {
1237  foundProcessorFace = true;
1238  }
1239  }
1240  }
1241 
1242  if (foundProcessorFace)
1243  {
1244  procIbCellsSet.insert(cellI);
1245  }
1246  }
1247  }
1248  labelList procIbCells = procIbCellsSet.toc();
1249  sort(procIbCells);
1250 
1251  // Note: consider more sophisticated gather-scatter
1252  // HJ, 18/Jun/2015
1253 
1254  // Send and receive number of immersed boundary cells
1255  // next to processor boundaries
1256  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1257  {
1258  if (procI != Pstream::myProcNo())
1259  {
1260  // Parallel data exchange
1261  {
1262  OPstream toProc
1263  (
1265  procI,
1266  sizeof(label)
1267  );
1268 
1269  toProc << procIbCells.size();
1270  }
1271  }
1272  }
1273 
1274  labelList sizes(Pstream::nProcs(), 0);
1275  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1276  {
1277  if (procI != Pstream::myProcNo())
1278  {
1279  // Parallel data exchange
1280  {
1281  IPstream fromProc
1282  (
1284  procI,
1285  sizeof(label)
1286  );
1287 
1288  fromProc >> sizes[procI];
1289  }
1290  }
1291  }
1292 
1293  // Send and receive ibc centres and radii
1294  vectorField centres(procIbCells.size(), vector::zero);
1295  forAll (centres, cellI)
1296  {
1297  centres[cellI] = C[ibc[procIbCells[cellI]]];
1298  }
1299  scalarField procRMax(rM, procIbCells);
1300 
1301  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1302  {
1303  if (procI != Pstream::myProcNo())
1304  {
1305  // Parallel data exchange
1306  {
1307  OPstream toProc
1308  (
1310  procI,
1311  centres.size()*sizeof(vector)
1312  + procRMax.size()*sizeof(scalar)
1313  );
1314 
1315  toProc << centres << procRMax;
1316  }
1317  }
1318  }
1319 
1322 
1323  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1324  {
1325  if (procI != Pstream::myProcNo())
1326  {
1327  ctrs.set
1328  (
1329  procI,
1330  new vectorField(sizes[procI], vector::zero)
1331  );
1332 
1333  rMax.set
1334  (
1335  procI,
1336  new scalarField(sizes[procI], 0)
1337  );
1338 
1339  // Parallel data exchange
1340  {
1341  IPstream fromProc
1342  (
1344  procI,
1345  sizes[procI]*sizeof(vector)
1346  + sizes[procI]*sizeof(scalar)
1347  );
1348 
1349  fromProc >> ctrs[procI] >> rMax[procI];
1350  }
1351  }
1352  else
1353  {
1354  ctrs.set(procI, new vectorField(0));
1355  rMax.set(procI, new scalarField(0));
1356  }
1357  }
1358 
1359  // Find cells needed by other processors
1360  if (ibProcCellsPtr_)
1361  {
1362  FatalErrorIn("immersedBoundaryFvPatch::makeIbCellCells() const")
1363  << "procCells addressing already exists"
1364  << abort(FatalError);
1365  }
1366 
1367  ibProcCellsPtr_ = new labelListList(Pstream::nProcs());
1368  labelListList& procCells = *ibProcCellsPtr_;
1369 
1370  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1371  {
1372  labelHashSet procCellSet;
1373 
1374  if (procI != Pstream::myProcNo())
1375  {
1376  forAll (ctrs[procI], cellI)
1377  {
1378  label nearestCellID =
1379  findNearestCell(ctrs[procI][cellI]);
1380 
1381  if (nearestCellID == -1)
1382  {
1383  FatalErrorIn
1384  (
1385  "immersedBoundaryFvPatch::makeIbCellCells() const"
1386  ) << "Can't find nearest cell."
1387  << abort(FatalError);
1388  }
1389 
1390  scalar R = mag(C[nearestCellID] - ctrs[procI][cellI]);
1391 
1392  if (R < rMax[procI][cellI])
1393  {
1394  if (!procCellSet.found(nearestCellID))
1395  {
1396  procCellSet.insert(nearestCellID);
1397  }
1398 
1399  labelList tmpCellList;
1400 
1401  findCellCells
1402  (
1403  ctrs[procI][cellI],
1404  nearestCellID,
1405  tmpCellList
1406  );
1407 
1408  forAll (tmpCellList, cI)
1409  {
1410  scalar r =
1411  mag
1412  (
1413  C[tmpCellList[cI]]
1414  - ctrs[procI][cellI]
1415  );
1416 
1417  if (r <= rMax[procI][cellI])
1418  {
1419  if (!procCellSet.found(tmpCellList[cI]))
1420  {
1421  procCellSet.insert(tmpCellList[cI]);
1422  }
1423  }
1424  }
1425  }
1426  }
1427  }
1428 
1429  procCells[procI] = procCellSet.toc();
1430  }
1431 
1432 
1433  // Send and receive sizes
1434  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1435  {
1436  if (procI != Pstream::myProcNo())
1437  {
1438  // Parallel data exchange
1439  {
1440  OPstream toProc
1441  (
1443  procI,
1444  sizeof(label)
1445  );
1446 
1447  toProc << procCells[procI].size();
1448  }
1449  }
1450  }
1451 
1452  labelList procSizes(Pstream::nProcs(), 0);
1453  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1454  {
1455  if (procI != Pstream::myProcNo())
1456  {
1457  // Parallel data exchange
1458  {
1459  IPstream fromProc
1460  (
1462  procI,
1463  sizeof(label)
1464  );
1465 
1466  fromProc >> procSizes[procI];
1467  }
1468  }
1469  }
1470 
1471  // Send cell centres
1472  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1473  {
1474  if (procI != Pstream::myProcNo())
1475  {
1476  vectorField centres(C, procCells[procI]);
1477 
1478  // Parallel data exchange
1479  {
1480  OPstream toProc
1481  (
1483  procI,
1484  centres.size()*sizeof(vector)
1485  );
1486 
1487  toProc << centres;
1488  }
1489  }
1490  }
1491 
1492  // Receive cell centres
1493  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1494  {
1495  if (procI != Pstream::myProcNo())
1496  {
1497  procCentres[procI].setSize(procSizes[procI]);
1498 
1499  // Parallel data exchange
1500  {
1501  IPstream fromProc
1502  (
1504  procI,
1505  procSizes[procI]*sizeof(vector)
1506  );
1507 
1508  fromProc >> procCentres[procI];
1509  }
1510  }
1511  // else: already set to zero-size field
1512  }
1513 
1514  // Send cell gamma
1515  const scalarField& gammaI = gamma().internalField();
1516  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1517  {
1518  if (procI != Pstream::myProcNo())
1519  {
1520  scalarField gamma(gammaI, procCells[procI]);
1521 
1522  // Parallel data exchange
1523  {
1524  OPstream toProc
1525  (
1527  procI,
1528  gamma.size()*sizeof(scalar)
1529  );
1530 
1531  toProc << gamma;
1532  }
1533  }
1534  }
1535 
1536  // Receive cell gamma
1537  for (label procI = 0; procI < Pstream::nProcs(); procI++)
1538  {
1539  if (procI != Pstream::myProcNo())
1540  {
1541  procGamma[procI].setSize(procSizes[procI]);
1542 
1543  // Parallel data exchange
1544  {
1545  IPstream fromProc
1546  (
1548  procI,
1549  procSizes[procI]*sizeof(scalar)
1550  );
1551 
1552  fromProc >> procGamma[procI];
1553  }
1554  }
1555  // else: already set to zero-size field
1556  }
1557 
1558  // Cell-procCells addressing
1559  forAll (cellProcCells, cellI)
1560  {
1561  scalar rMax = rM[cellI];
1562 
1563  cellProcCells[cellI].setSize(100);
1564 
1565  label index = 0;
1566  forAll (procCentres, procI)
1567  {
1568  forAll (procCentres[procI], pointI)
1569  {
1570  scalar r =
1571  mag
1572  (
1573  procCentres[procI][pointI]
1574  - C[ibc[cellI]]
1575  );
1576 
1577  if (r <= rMax)
1578  {
1579  cellProcCells[cellI][index].first() = procI;
1580  cellProcCells[cellI][index].second() = pointI;
1581  index++;
1582  }
1583  }
1584  }
1585 
1586  cellProcCells[cellI].setSize(index);
1587  }
1588  }
1589 }
1590 
1591 
1593 {
1594  if (debug)
1595  {
1596  InfoIn("void immersedBoundaryFvPatch::makeDeadCells() const")
1597  << "create list of dead cells"
1598  << endl;
1599  }
1600 
1601  // It is an error to attempt to recalculate
1602  // if the pointer is already set
1603  if (deadCellsPtr_)
1604  {
1605  FatalErrorIn("immersedBoundaryFvPatch::makeDeadCells() const")
1606  << "list of dead cells already exist"
1607  << abort(FatalError);
1608  }
1609 
1610  const scalarField& gammaExtI = gammaExt().internalField();
1611 
1612  deadCellsPtr_ = new labelList(label(sum(scalar(1) - gammaExtI)), -1);
1613  labelList& deadCells = *deadCellsPtr_;
1614 
1615  label counter = 0;
1616 
1617  forAll (gammaExtI, cellI)
1618  {
1619  if (gammaExtI[cellI] < SMALL)
1620  {
1621  deadCells[counter++] = cellI;
1622  }
1623  }
1624 }
1625 
1626 
1628 {
1629  if (debug)
1630  {
1631  InfoIn("void immersedBoundaryFvPatch::makeDeadCellsExt() const")
1632  << "create extended list of dead cells"
1633  << endl;
1634  }
1635 
1636  // It is an error to attempt to recalculate
1637  // if the pointer is already set
1638  if (deadCellsExtPtr_)
1639  {
1640  FatalErrorIn("immersedBoundaryFvPatch::makeDeadCellsExt() const")
1641  << "extended list of dead cells already exist"
1642  << abort(FatalError);
1643  }
1644 
1645  const scalarField& gammaI = gamma().internalField();
1646 
1647  deadCellsExtPtr_ = new labelList(label(sum(scalar(1) - gammaI)), -1);
1648  labelList& deadCellsExt = *deadCellsExtPtr_;
1649 
1650  label counter = 0;
1651  forAll (gammaI, cellI)
1652  {
1653  if (gammaI[cellI] < SMALL)
1654  {
1655  deadCellsExt[counter++] = cellI;
1656  }
1657  }
1658 }
1659 
1660 
1662 {
1663  if (debug)
1664  {
1665  InfoIn("void immersedBoundaryFvPatch::makeDeadFaces() const")
1666  << "create list of dead cells"
1667  << endl;
1668  }
1669 
1670  // It is an error to attempt to recalculate
1671  // if the pointer is already set
1672  if (deadFacesPtr_)
1673  {
1674  FatalErrorIn("immersedBoundaryFvPatch::makeDeadFaces() const")
1675  << "list of dead cells already exist"
1676  << abort(FatalError);
1677  }
1678 
1679  deadFacesPtr_ = new labelList(mesh_.nFaces());
1680  labelList& df = *deadFacesPtr_;
1681  label nDf = 0;
1682 
1683  const volScalarField& gE = gammaExt();
1684  const scalarField& gammaExtI = gE.internalField();
1685 
1686  const volScalarField::GeometricBoundaryField& gEPatches =
1687  gE.boundaryField();
1688 
1689  const labelList& owner = mesh_.faceOwner();
1690  const labelList& neighbour = mesh_.faceNeighbour();
1691 
1692  forAll (neighbour, faceI)
1693  {
1694  if (gammaExtI[neighbour[faceI]] + gammaExtI[owner[faceI]] < SMALL)
1695  {
1696  df[nDf] = faceI;
1697  nDf++;
1698  }
1699  }
1700 
1701  forAll (gEPatches, patchI)
1702  {
1703  const label start = mesh_.boundaryMesh()[patchI].start();
1704 
1705  if (gEPatches[patchI].coupled())
1706  {
1707  scalarField gammaExtOwn =
1708  gEPatches[patchI].patchInternalField();
1709 
1710  scalarField gammaExtNei =
1711  gEPatches[patchI].patchNeighbourField();
1712 
1713  forAll (gammaExtOwn, patchFaceI)
1714  {
1715  if
1716  (
1717  gammaExtNei[patchFaceI] + gammaExtOwn[patchFaceI] < SMALL
1718  )
1719  {
1720  df[nDf] = start + patchFaceI;
1721  nDf++;
1722  }
1723  }
1724  }
1725  else
1726  {
1727  scalarField gammaExtOwn =
1728  gEPatches[patchI].patchInternalField();
1729 
1730  forAll (gammaExtOwn, patchFaceI)
1731  {
1732  if (gammaExtOwn[patchFaceI] < SMALL)
1733  {
1734  df[nDf] = start + patchFaceI;
1735  nDf++;
1736  }
1737  }
1738  }
1739  }
1740 
1741  df.setSize(nDf);
1742 }
1743 
1744 
1746 {
1747  if (debug)
1748  {
1749  InfoIn("void immersedBoundaryFvPatch::makeLiveCells() const")
1750  << "create list of live cells"
1751  << endl;
1752  }
1753 
1754  // It is an error to attempt to recalculate
1755  // if the pointer is already set
1756  if (liveCellsPtr_)
1757  {
1758  FatalErrorIn("immersedBoundaryFvPatch::makeLiveCells() const")
1759  << "list of live cells already exist"
1760  << abort(FatalError);
1761  }
1762 
1763  const scalarField& gammaI = gamma().internalField();
1764 
1765  liveCellsPtr_ = new labelList(label(sum(gammaI)), -1);
1766  labelList& liveCells = *liveCellsPtr_;
1767 
1768  label counter = 0;
1769  forAll (gammaI, cellI)
1770  {
1771  if (gammaI[cellI] > (1.0 - SMALL))
1772  {
1773  liveCells[counter++] = cellI;
1774  }
1775  }
1776 }
1777 
1778 
1780 {
1781  if (debug)
1782  {
1783  InfoIn("void immersedBoundaryFvPatch::makeIbCellsSize() const")
1784  << "create average sizes of immersed boundary cells"
1785  << endl;
1786  }
1787 
1788  // It is an error to attempt to recalculate
1789  // if the pointer is already set
1790  if (ibCellSizesPtr_)
1791  {
1792  FatalErrorIn("immersedBoundaryFvPatch::makeIbCellsSize() const")
1793  << "average sizes of immersed boundary cells already exist"
1794  << abort(FatalError);
1795  }
1796 
1797  ibCellSizesPtr_ = new scalarField(ibPoints().size(), 0.0);
1798  scalarField& delta = *ibCellSizesPtr_;
1799 
1800  if (mesh_.nGeometricD() == 3)
1801  {
1802  // Create a list of volumes with mapping to contain only IB cells
1803  scalarField V(mesh_.V().field(), ibCells());
1804 
1805  delta = Foam::pow(V, 1.0/3.0);
1806  }
1807  else
1808  {
1809  // For 2-D simulations with the immersed boundary method the geometry
1810  // needs to be aligned with the z-direction.
1811  // Having the x- or y-direction as empty is not allowed because of
1812  // the way the polynomials are expanded
1813  const Vector<label>& directions = mesh_.geometricD();
1814 
1815  if (directions[0] == -1 || directions[1] == -1)
1816  {
1817  FatalErrorIn("immersedBoundaryFvPatch::makeIbCellsSize() const")
1818  << "For 2-D simulations with the immersed boundary method "
1819  << "the geometry needs to be aligned with the z-direction. "
1820  << "Having the x- or y-direction as empty is not allowed "
1821  << "because of the way the polynomials are expanded."
1822  << abort(FatalError);
1823  }
1824 
1825  scalar thickness = 0.0;
1826 
1827  for (direction dir = 0; dir < directions.nComponents; dir++)
1828  {
1829  if (directions[dir] == -1)
1830  {
1831  thickness = mesh_.bounds().span()[dir];
1832  break;
1833  }
1834  }
1835 
1836  // Field created with mapping for IB cells only
1837  delta = sqrt(scalarField(mesh_.V().field(), ibCells())/thickness);
1838  }
1839 }
1840 
1841 
1843 {
1844  if (debug)
1845  {
1846  InfoIn("void immersedBoundaryFvPatch::makeIbSf() const")
1847  << "creating ibSf and ibMagSf field"
1848  << endl;
1849  }
1850 
1851  // It is an error to attempt to recalculate
1852  // if the pointer is already set
1853  if (ibSfPtr_ || ibMagSfPtr_)
1854  {
1855  FatalErrorIn("immersedBoundaryFvPatch::makeIbSf() const")
1856  << "ibSf and ibMagSf field already exist"
1857  << abort(FatalError);
1858  }
1859 
1860  const vectorField& areas = mesh_.faceAreas();
1861 
1862  // Field created with mapping for IB cells only
1863  ibSfPtr_ = new vectorField(areas, ibFaces());
1864  ibMagSfPtr_ = new scalarField(mag(*ibSfPtr_));
1865 }
1866 
1867 
1869 {
1870  if (debug)
1871  {
1872  InfoIn("void immersedBoundaryFvPatch::makeIbDelta() const")
1873  << "creating delta field"
1874  << endl;
1875  }
1876 
1877  // It is an error to attempt to recalculate
1878  // if the pointer is already set
1879  if (ibDeltaPtr_)
1880  {
1881  FatalErrorIn("immersedBoundaryFvPatch::makeIbDelta() const")
1882  << "delta field already exist"
1883  << abort(FatalError);
1884  }
1885 
1886  const vectorField& C = mesh_.cellCentres();
1887 
1888  // Field created with mapping for IB cells only
1889  ibDeltaPtr_ =
1890  new scalarField(mag(ibPoints() - vectorField(C, ibCells())) + SMALL);
1891 }
1892 
1893 
1895 {
1896  if (debug)
1897  {
1898  InfoIn
1899  (
1900  "void immersedBoundaryFvPatch::makeIbSamplingPointDelta() const"
1901  ) << "creating sampling point delta field"
1902  << endl;
1903  }
1904 
1905  // It is an error to attempt to recalculate
1906  // if the pointer is already set
1907  if (ibSamplingPointDeltaPtr_)
1908  {
1909  FatalErrorIn
1910  (
1911  "immersedBoundaryFvPatch::makeIbSamplingPointDelta() const"
1912  ) << "sampling point delta field already exist"
1913  << abort(FatalError);
1914  }
1915 
1916  // Field created with mapping for IB cells only
1917  ibSamplingPointDeltaPtr_ =
1918  new scalarField(mag(ibPoints() - ibSamplingPoints()) + SMALL);
1919 }
1920 
1921 
1923 {
1924  if (debug)
1925  {
1926  InfoIn("void immersedBoundaryFvPatch::makeTriSf() const")
1927  << "creating delta field"
1928  << endl;
1929  }
1930 
1931  // It is an error to attempt to recalculate
1932  // if the pointer is already set
1933  if (triSfPtr_)
1934  {
1935  FatalErrorIn("immersedBoundaryFvPatch::makeTriSf() const")
1936  << "triSf field already exist"
1937  << abort(FatalError);
1938  }
1939 
1940 
1941  const triSurface& triMesh = ibPolyPatch_.ibMesh();
1942  const pointField& triMeshPoints = triMesh.points();
1943 
1944  triSfPtr_ = new vectorField(triMesh.size());
1945  vectorField& Sf = *triSfPtr_;
1946 
1947  forAll (triMesh, faceI)
1948  {
1949  Sf[faceI] = triMesh[faceI].normal(triMeshPoints);
1950  }
1951 
1952  if (!ibPolyPatch_.internalFlow())
1953  {
1954  // Tri surface points the wrong way; flip all area vectors
1955  Sf *= -1;
1956  }
1957 }
1958 
1959 
1960 // Find the cell with the nearest cell centre
1963  const point& location
1964 ) const
1965 {
1966  const vectorField& C = mesh_.cellCentres();
1967 
1968  const scalarField& gammaExtI = gammaExt().internalField();
1969 
1970  label nearestCellI = -1;
1971  scalar minProximity = GREAT;
1972 
1973  for (label cellI = 0; cellI < C.size(); cellI++)
1974  {
1975  if (gammaExtI[cellI] > SMALL)
1976  {
1977  scalar proximity = magSqr(C[cellI] - location);
1978 
1979  if (proximity < minProximity)
1980  {
1981  nearestCellI = cellI;
1982  minProximity = proximity;
1983  }
1984  }
1985  }
1986 
1987  return nearestCellI;
1988 }
1989 
1990 
1993  const vector& pt,
1994  const label cellID,
1995  labelList& cellCells
1996 ) const
1997 {
1998  const labelListList& cellPoints = mesh_.cellPoints();
1999  const labelListList& pointCells = mesh_.pointCells();
2000 
2001  const scalarField& gammaExtI = gammaExt().internalField();
2002 
2004  cellSet.insert(cellID);
2005 
2006  // First row
2007  const labelList& curCellPoints = cellPoints[cellID];
2008 
2009  forAll (curCellPoints, pointI)
2010  {
2011  label curPoint = curCellPoints[pointI];
2012  const labelList& curPointCells = pointCells[curPoint];
2013 
2014  forAll (curPointCells, cI)
2015  {
2016  if (gammaExtI[curPointCells[cI]] > SMALL)
2017  {
2018  if (!cellSet.found(curPointCells[cI]))
2019  {
2020  cellSet.insert(curPointCells[cI]);
2021  }
2022  }
2023  }
2024  }
2025 
2026  labelList curCells = cellSet.toc();
2027 
2028  // Second and other rows
2029  for (label nRows = 1; nRows < maxCellCellRows_(); nRows++)
2030  {
2031  curCells = cellSet.toc();
2032 
2033  forAll (curCells, cellI)
2034  {
2035  label curCell = curCells[cellI];
2036  const labelList& curCellPoints = cellPoints[curCell];
2037 
2038  forAll (curCellPoints, pointI)
2039  {
2040  label curPoint = curCellPoints[pointI];
2041  const labelList& curPointCells = pointCells[curPoint];
2042 
2043  forAll (curPointCells, cI)
2044  {
2045  if (gammaExtI[curPointCells[cI]] > SMALL)
2046  {
2047  if (!cellSet.found(curPointCells[cI]))
2048  {
2049  cellSet.insert(curPointCells[cI]);
2050  }
2051  }
2052  }
2053  }
2054  }
2055  }
2056 
2057  // Erase current cell
2058  cellSet.erase(cellID);
2059 
2060  // Sorting cells
2061  const vectorField& C = mesh_.cellCentres();
2062 
2063  curCells = cellSet.toc();
2064  scalarField distances(curCells.size(), 0);
2065 
2066  forAll (distances, cI)
2067  {
2068  distances[cI] =
2069  mag(C[curCells[cI]] - pt);
2070  }
2071 
2072  SortableList<scalar> sortedDistances(distances);
2073 
2074  labelList sortedCells(curCells.size(), -1);
2075 
2076  for (label i = 0; i < sortedCells.size(); i++)
2077  {
2078  sortedCells[i] =
2079  curCells[sortedDistances.indices()[i]];
2080  }
2081 
2082  cellCells = sortedCells;
2083 }
2084 
2085 
2087 {
2088  scalar delta;
2089 
2090  if (mesh_.nGeometricD() == 3)
2091  {
2092  delta = Foam::pow(mesh_.V().field()[cellID], 1.0/3.0);
2093  }
2094  else
2095  {
2096  scalar thickness = 0.0;
2097  const Vector<label>& directions = mesh_.geometricD();
2098  for (direction dir = 0; dir < directions.nComponents; dir++)
2099  {
2100  if (directions[dir] == -1)
2101  {
2102  thickness = mesh_.bounds().span()[dir];
2103  break;
2104  }
2105  }
2106 
2107  delta = sqrt(mesh_.V().field()[cellID]/thickness);
2108  }
2109 
2110  return delta;
2111 }
2112 
2113 
2116  label cellID,
2117  const vector& dir
2118 ) const
2119 {
2120  const vectorField& C = mesh_.cellCentres();
2121  const vectorField& Cf = mesh_.faceCentres();
2122  const vectorField& Sf = mesh_.faceAreas();
2123 
2124  const labelList& cellFaces = mesh_.cells()[cellID];
2125 
2126  scalar area = 0;
2127 
2128  forAll (cellFaces, faceI)
2129  {
2130  label curFace = cellFaces[faceI];
2131 
2132  vector curSf = Sf[curFace];
2133 
2134  if ((curSf & (Cf[curFace] - C[cellID])) < 0)
2135  {
2136  curSf *= -1;
2137  }
2138 
2139  if ((curSf&dir) > 1)
2140  {
2141  area += (curSf & dir);
2142  }
2143  }
2144 
2145  return area;
2146 }
2147 
2148 
2150 {
2151  deleteDemandDrivenData(gammaPtr_);
2152  deleteDemandDrivenData(gammaExtPtr_);
2153  deleteDemandDrivenData(sGammaPtr_);
2154  deleteDemandDrivenData(ibCellsPtr_);
2155  deleteDemandDrivenData(ibFacesPtr_);
2156  deleteDemandDrivenData(ibFaceCellsPtr_);
2157  deleteDemandDrivenData(ibFaceFlipsPtr_);
2158  deleteDemandDrivenData(ibInsideFacesPtr_);
2159  deleteDemandDrivenData(ibInternalFacesPtr_);
2160  deleteDemandDrivenData(ibPointsPtr_);
2161  deleteDemandDrivenData(ibNormalsPtr_);
2162  deleteDemandDrivenData(hitFacesPtr_);
2163  deleteDemandDrivenData(ibSamplingPointsPtr_);
2164 
2165  deleteDemandDrivenData(ibSamplingWeightsPtr_);
2166  deleteDemandDrivenData(ibSamplingProcWeightsPtr_);
2167 
2168  deleteDemandDrivenData(cellsToTriAddrPtr_);
2169  deleteDemandDrivenData(cellsToTriWeightsPtr_);
2170 
2171  deleteDemandDrivenData(ibCellCellsPtr_);
2172  deleteDemandDrivenData(ibProcCellsPtr_);
2173  deleteDemandDrivenData(ibProcCentresPtr_);
2174  deleteDemandDrivenData(ibProcGammaPtr_);
2175  deleteDemandDrivenData(ibCellProcCellsPtr_);
2176  deleteDemandDrivenData(deadCellsPtr_);
2177  deleteDemandDrivenData(deadCellsExtPtr_);
2178  deleteDemandDrivenData(deadFacesPtr_);
2179  deleteDemandDrivenData(liveCellsPtr_);
2180  deleteDemandDrivenData(ibCellSizesPtr_);
2181 
2182  deleteDemandDrivenData(invDirichletMatricesPtr_);
2183  deleteDemandDrivenData(invNeumannMatricesPtr_);
2184 
2185  deleteDemandDrivenData(ibSfPtr_);
2186  deleteDemandDrivenData(ibMagSfPtr_);
2187  deleteDemandDrivenData(ibDeltaPtr_);
2188  deleteDemandDrivenData(ibSamplingPointDeltaPtr_);
2189 
2190  deleteDemandDrivenData(triSfPtr_);
2191 }
2192 
2193 
2194 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
2195 
2197 {}
2198 
2199 
2201 {
2202  clearOut();
2203 }
2204 
2205 
2206 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
2207 
2210  const polyPatch& patch,
2211  const fvBoundaryMesh& bm
2212 )
2213 :
2214  fvPatch(patch, bm),
2215  ibPolyPatch_(refCast<const immersedBoundaryPolyPatch>(patch)),
2216  mesh_(bm.mesh()),
2217  gammaPtr_(NULL),
2218  gammaExtPtr_(NULL),
2219  sGammaPtr_(NULL),
2220  ibCellsPtr_(NULL),
2221  ibFacesPtr_(NULL),
2222  ibFaceCellsPtr_(NULL),
2223  ibFaceFlipsPtr_(NULL),
2224  ibInsideFacesPtr_(NULL),
2225  ibInternalFacesPtr_(NULL),
2226  ibPointsPtr_(NULL),
2227  ibNormalsPtr_(NULL),
2228  hitFacesPtr_(NULL),
2229  ibSamplingPointsPtr_(NULL),
2230  ibSamplingWeightsPtr_(NULL),
2231  ibSamplingProcWeightsPtr_(NULL),
2232  cellsToTriAddrPtr_(NULL),
2233  cellsToTriWeightsPtr_(NULL),
2234  ibCellCellsPtr_(NULL),
2235  ibProcCellsPtr_(NULL),
2236  ibProcCentresPtr_(NULL),
2237  ibProcGammaPtr_(NULL),
2238  ibCellProcCellsPtr_(NULL),
2239  deadCellsPtr_(NULL),
2240  deadCellsExtPtr_(NULL),
2241  deadFacesPtr_(NULL),
2242  liveCellsPtr_(NULL),
2243  ibCellSizesPtr_(NULL),
2244  invDirichletMatricesPtr_(NULL),
2245  invNeumannMatricesPtr_(NULL),
2246  ibSfPtr_(NULL),
2247  ibMagSfPtr_(NULL),
2248  ibDeltaPtr_(NULL),
2249  ibSamplingPointDeltaPtr_(NULL),
2250  triSfPtr_(NULL)
2251 {}
2252 
2253 
2254 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2255 
2257 {
2258  if (!gammaPtr_)
2259  {
2260  makeGamma();
2261  }
2262 
2263  return *gammaPtr_;
2264 }
2265 
2266 
2268 {
2269  if (!gammaExtPtr_)
2270  {
2271  makeGammaExt();
2272  }
2273 
2274  return *gammaExtPtr_;
2275 }
2276 
2277 
2279 {
2280  if (!sGammaPtr_)
2281  {
2282  makeSGamma();
2283  }
2284 
2285  return *sGammaPtr_;
2286 }
2287 
2288 
2290 {
2291  if (!ibCellsPtr_)
2292  {
2293  makeIbCells();
2294  }
2295 
2296  return *ibCellsPtr_;
2297 }
2298 
2299 
2301 {
2302  if (!ibFacesPtr_)
2303  {
2304  makeIbFaces();
2305  }
2306 
2307  return *ibFacesPtr_;
2308 }
2309 
2310 
2312 {
2313  if (!ibFaceCellsPtr_)
2314  {
2315  makeIbFaces();
2316  }
2317 
2318  return *ibFaceCellsPtr_;
2319 }
2320 
2321 
2323 {
2324  if (!ibFaceFlipsPtr_)
2325  {
2326  makeIbFaces();
2327  }
2328 
2329  return *ibFaceFlipsPtr_;
2330 }
2331 
2332 
2334 {
2335  if (!ibInsideFacesPtr_)
2336  {
2337  makeIbInsideFaces();
2338  }
2339 
2340  return *ibInsideFacesPtr_;
2341 }
2342 
2343 
2345 {
2346  if (!ibInternalFacesPtr_)
2347  {
2348  makeIbInternalFaces();
2349  }
2350 
2351  return *ibInternalFacesPtr_;
2352 }
2353 
2354 
2356 {
2357  if (!ibPointsPtr_)
2358  {
2359  makeIbPointsAndNormals();
2360  }
2361 
2362  return *ibPointsPtr_;
2363 }
2364 
2365 
2367 {
2368  if (!ibNormalsPtr_)
2369  {
2370  makeIbPointsAndNormals();
2371  }
2372 
2373  return *ibNormalsPtr_;
2374 }
2375 
2376 
2378 {
2379  if (!hitFacesPtr_)
2380  {
2381  makeIbPointsAndNormals();
2382  }
2383 
2384  return *hitFacesPtr_;
2385 }
2386 
2387 
2388 const Foam::vectorField&
2390 {
2391  if (!ibSamplingPointsPtr_)
2392  {
2393  makeIbPointsAndNormals();
2394  }
2395 
2396  return *ibSamplingPointsPtr_;
2397 }
2398 
2399 
2401 {
2402  if (!ibCellCellsPtr_)
2403  {
2404  makeIbCellCells();
2405  }
2406 
2407  return *ibCellCellsPtr_;
2408 }
2409 
2410 
2413 {
2414  if (!ibProcCentresPtr_)
2415  {
2416  makeIbCellCells();
2417  }
2418 
2419  return *ibProcCentresPtr_;
2420 }
2421 
2422 
2425 {
2426  if (!ibProcGammaPtr_)
2427  {
2428  makeIbCellCells();
2429  }
2430 
2431  return *ibProcGammaPtr_;
2432 }
2433 
2434 
2437 {
2438  if (!ibCellProcCellsPtr_)
2439  {
2440  makeIbCellCells();
2441  }
2442 
2443  return *ibCellProcCellsPtr_;
2444 }
2445 
2446 
2448 {
2449  if (!ibProcCellsPtr_)
2450  {
2451  makeIbCellCells();
2452  }
2453 
2454  return *ibProcCellsPtr_;
2455 }
2456 
2457 
2459 {
2460  if (!deadCellsPtr_)
2461  {
2462  makeDeadCells();
2463  }
2464 
2465  return *deadCellsPtr_;
2466 }
2467 
2468 
2470 {
2471  if (!deadCellsExtPtr_)
2472  {
2473  makeDeadCellsExt();
2474  }
2475 
2476  return *deadCellsExtPtr_;
2477 }
2478 
2479 
2481 {
2482  if (!deadFacesPtr_)
2483  {
2484  makeDeadFaces();
2485  }
2486 
2487  return *deadFacesPtr_;
2488 }
2489 
2490 
2492 {
2493  if (!liveCellsPtr_)
2494  {
2495  makeLiveCells();
2496  }
2497 
2498  return *liveCellsPtr_;
2499 }
2500 
2501 
2503 {
2504  if (!ibCellSizesPtr_)
2505  {
2506  makeIbCellSizes();
2507  }
2508 
2509  return *ibCellSizesPtr_;
2510 }
2511 
2512 
2514 {
2515  if (!ibSfPtr_)
2516  {
2517  makeIbSf();
2518  }
2519 
2520  return *ibSfPtr_;
2521 }
2522 
2523 
2525 {
2526  if (!ibMagSfPtr_)
2527  {
2528  makeIbSf();
2529  }
2530 
2531  return *ibMagSfPtr_;
2532 }
2533 
2534 
2536 {
2537  if (!ibDeltaPtr_)
2538  {
2539  makeIbDelta();
2540  }
2541 
2542  return *ibDeltaPtr_;
2543 }
2544 
2545 
2546 const Foam::scalarField&
2548 {
2549  if (!ibSamplingPointDeltaPtr_)
2550  {
2551  makeIbSamplingPointDelta();
2552  }
2553 
2554  return *ibSamplingPointDeltaPtr_;
2555 }
2556 
2557 
2559 {
2560  if (!triSfPtr_)
2561  {
2562  makeTriSf();
2563  }
2564 
2565  return *triSfPtr_;
2566 }
2567 
2568 
2570 {
2571  return ibMesh().faceCentres();
2572 }
2573 
2574 
2575 const Foam::dynamicLabelList&
2577 {
2578  // Check if triFacesInMesh has been updated this time step
2579  if(ibUpdateTimeIndex_ != mesh_.time().timeIndex())
2580  {
2581  const vectorField& triCf = this->triCf();
2582 
2583  triFacesInMesh_.clear();
2584  triFacesInMesh_.setCapacity(triCf.size()/2);
2585 
2586  // Find tri faces with centre inside the processor mesh
2587  forAll(triCf, fI)
2588  {
2589  const vector curTriCf = triCf[fI];
2590 
2591  if(!mesh_.bounds().containsInside(curTriCf))
2592  {
2593  // Face centre is not inside the mesh
2594  continue;
2595  }
2596  else
2597  {
2598  if(mesh_.findCell(curTriCf) != -1)
2599  {
2600  triFacesInMesh_.append(fI);
2601  }
2602  }
2603  }
2604 
2605  ibUpdateTimeIndex_ = mesh_.time().timeIndex();
2606  }
2607 
2608  return triFacesInMesh_;
2609 }
2610 
2611 
2612 // ************************************************************************* //
volFields.H
Foam::immersedBoundaryFvPatch::maxCellCellRows_
static const debug::optimisationSwitch maxCellCellRows_
Maximum number of rows in cell-cell search.
Definition: immersedBoundaryFvPatch.H:93
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:48
Foam::immersedBoundaryFvPatch::ibSamplingPointDelta
const scalarField & ibSamplingPointDelta() const
Return distance to IB.
Definition: immersedBoundaryFvPatch.C:2547
Foam::IOobject
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
Foam::DynamicList::xfer
Xfer< List< T > > xfer()
Transfer contents to the Xfer container as a plain List.
Definition: DynamicListI.H:301
Foam::PointIndexHit::index
label index() const
Return index.
Definition: PointIndexHit.H:111
InfoIn
#define InfoIn(functionName)
Report a information message using Foam::Info.
Definition: messageStream.H:276
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
Foam::immersedBoundaryFvPatch::ibSf
const vectorField & ibSf() const
Return IB face area vectors.
Definition: immersedBoundaryFvPatch.C:2513
Foam::immersedBoundaryFvPatch::addIbCornerCells
void addIbCornerCells() const
Add corner points to IB cells list.
Definition: immersedBoundaryFvPatch.C:476
Foam::immersedBoundaryFvPatch::makeDeadFaces
void makeDeadFaces() const
Make list of dead faces.
Definition: immersedBoundaryFvPatch.C:1661
Foam::PrimitivePatch::points
const Field< PointType > & points() const
Return reference to global points.
Definition: PrimitivePatchTemplate.H:282
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
Foam::immersedBoundaryFvPatch::makeGamma
void makeGamma() const
Make fluid cells indicator, marking only live fluid cells.
Definition: immersedBoundaryFvPatch.C:83
Foam::immersedBoundaryFvPatch::ibCellSizes
const scalarField & ibCellSizes() const
Return immersed boundary cell sizes.
Definition: immersedBoundaryFvPatch.C:2502
Foam::FieldField
Generic field type.
Definition: FieldField.H:51
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
Foam::HashTable::toc
List< Key > toc() const
Return the table of contents.
Definition: HashTable.C:201
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
foamTime.H
Foam::immersedBoundaryFvPatch::hitFaces
const labelList & hitFaces() const
Return list of triangles in IB mesh nearest.
Definition: immersedBoundaryFvPatch.C:2377
Foam::triSurfaceSearch::nearest
pointIndexHit nearest(const point &, const vector &span) const
Calculate nearest point on surface for single searchPoint. Returns.
Definition: triSurfaceSearch.C:312
Foam::immersedBoundaryFvPatch::ibCellProcCells
const List< List< labelPair > > & ibCellProcCells() const
Return neighbour cell addressing.
Definition: immersedBoundaryFvPatch.C:2436
Foam::findIndex
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Foam::immersedBoundaryFvPatch::ibProcGamma
const FieldField< Field, scalar > & ibProcGamma() const
Return neighbour proc gamma.
Definition: immersedBoundaryFvPatch.C:2424
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:56
Foam::immersedBoundaryFvPatch::mesh_
const fvMesh & mesh_
Finite volume mesh reference.
Definition: immersedBoundaryFvPatch.H:76
Foam::OPstream
Output inter-processor communications stream.
Definition: OPstream.H:50
Foam::immersedBoundaryFvPatch::makeIbSf
void makeIbSf() const
Make face area vectors and magnitudes.
Definition: immersedBoundaryFvPatch.C:1842
Foam::immersedBoundaryFvPatch::triSf
const vectorField & triSf() const
Return triangular surface face area vectors.
Definition: immersedBoundaryFvPatch.C:2558
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
Foam::immersedBoundaryFvPatch::liveCells
const labelList & liveCells() const
Return live cells.
Definition: immersedBoundaryFvPatch.C:2491
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:387
Foam::immersedBoundaryFvPatch::clearOut
void clearOut()
Clear all demand-driven data.
Definition: immersedBoundaryFvPatch.C:2149
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:377
Foam::immersedBoundaryFvPatch::movePoints
virtual void movePoints()
Correct patches after moving points.
Definition: immersedBoundaryFvPatch.C:2200
Foam::immersedBoundaryFvPatch::ibSamplingPoints
const vectorField & ibSamplingPoints() const
Return IB sampling points.
Definition: immersedBoundaryFvPatch.C:2389
Foam::PointIndexHit::hit
bool hit() const
Is there a hit.
Definition: PointIndexHit.H:105
Foam::immersedBoundaryFvPatch::ibFaceCells
const labelList & ibFaceCells() const
Return list of IB cell index for each ibFace.
Definition: immersedBoundaryFvPatch.C:2311
Foam::immersedBoundaryFvPatch::sGamma
const surfaceScalarField & sGamma() const
Get fluid faces indicator, marking faces between live cells.
Definition: immersedBoundaryFvPatch.C:2278
Foam::GeometricField::boundaryField
GeometricBoundaryField & boundaryField()
Return reference to GeometricBoundaryField.
Definition: GeometricField.C:735
Foam::immersedBoundaryFvPatch::makeDeadCells
void makeDeadCells() const
Make list of dead cells.
Definition: immersedBoundaryFvPatch.C:1592
g
const dimensionedVector & g
Definition: setRegionFluidFields.H:33
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
surfaceFields.H
Foam::surfaceFields.
Foam::immersedBoundaryFvPatch::deadCells
const labelList & deadCells() const
Return dead cells.
Definition: immersedBoundaryFvPatch.C:2458
Foam::immersedBoundaryFvPatch::gammaPtr_
volScalarField * gammaPtr_
Fluid cells indicator, marking only live fluid cells.
Definition: immersedBoundaryFvPatch.H:106
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::fvBoundaryMesh::mesh
const fvMesh & mesh() const
Return the mesh reference.
Definition: fvBoundaryMesh.H:99
Foam::directions
Set of directions for each cell in the mesh. Either uniform and size=1 or one set of directions per c...
Definition: directions.H:63
Foam::HashSet< label, Hash< label > >
Foam::triSurfaceSearch
Helper class to search on triSurface.
Definition: triSurfaceSearch.H:55
Foam::immersedBoundaryFvPatch::findNearestCell
label findNearestCell(const point &location) const
Find nearest cell.
Definition: immersedBoundaryFvPatch.C:1962
Foam::immersedBoundaryFvPatch::gamma
const volScalarField & gamma() const
Get fluid cells indicator, marking only live fluid cells.
Definition: immersedBoundaryFvPatch.C:2256
Foam::IOobject::NO_WRITE
@ NO_WRITE
Definition: IOobject.H:118
Foam::immersedBoundaryFvPatch::makeDeadCellsExt
void makeDeadCellsExt() const
Make extended list of dead cells.
Definition: immersedBoundaryFvPatch.C:1627
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:49
Foam::immersedBoundaryFvPatch::triFacesInMesh
const dynamicLabelList & triFacesInMesh() const
Return labels of triangular faces which are inside the mesh.
Definition: immersedBoundaryFvPatch.C:2576
Foam::immersedBoundaryFvPatch::ibFaces
const labelList & ibFaces() const
Return list of faces for which one neighbour is an IB cell.
Definition: immersedBoundaryFvPatch.C:2300
Foam::fvPatch::name
const word & name() const
Return name.
Definition: fvPatch.H:149
Foam::fvBoundaryMesh
Foam::fvBoundaryMesh.
Definition: fvBoundaryMesh.H:52
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:40
Foam::UPstream::blocking
@ blocking
Definition: UPstream.H:66
n
label n
Definition: TABSMDCalcMethod2.H:31
SortableList.H
Foam::debug::optimisationSwitch
int optimisationSwitch(const char *name, const int defaultValue=0)
Lookup optimisation switch or add default value.
Definition: debug.C:182
R
#define R(A, B, C, D, E, F, K, M)
Foam::PointIndexHit
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:53
Foam::immersedBoundaryFvPatch::cellProjection
scalar cellProjection(label cellID, const vector &dir) const
Calc cell projection area.
Definition: immersedBoundaryFvPatch.C:2115
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:59
Foam::immersedBoundaryFvPatch::makeSGamma
void makeSGamma() const
Make fluid faces indicator.
Definition: immersedBoundaryFvPatch.C:217
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::triSurfaceTools::surfaceNormal
static vector surfaceNormal(const triSurface &surf, const label nearestFaceI, const point &nearestPt)
Triangle (unit) normal. If nearest point to triangle on edge use.
Definition: triSurfaceTools.C:2097
Foam::immersedBoundaryFvPatch::ibCells
const labelList & ibCells() const
Return list of fluid cells next to immersed boundary (IB cells)
Definition: immersedBoundaryFvPatch.C:2289
Foam::immersedBoundaryFvPatch::immersedBoundaryFvPatch
immersedBoundaryFvPatch(const polyPatch &patch, const fvBoundaryMesh &bm)
Construct from polyPatch.
Definition: immersedBoundaryFvPatch.C:2209
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:57
Foam::IOobject::NO_READ
@ NO_READ
Definition: IOobject.H:111
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::immersedBoundaryFvPatch::initMovePoints
virtual void initMovePoints()
Initialise the patches for moving points.
Definition: immersedBoundaryFvPatch.C:2196
Foam::PointIndexHit::hitPoint
const Point & hitPoint() const
Return hit point.
Definition: PointIndexHit.H:117
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::fvPatch
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:61
delta
scalar delta
Definition: LISASMDCalcMethod2.H:8
Foam::immersedBoundaryFvPatch::makeGammaExt
void makeGammaExt() const
Make extended fluid cells indicator, marking live and IB cells.
Definition: immersedBoundaryFvPatch.C:145
Foam::immersedBoundaryFvPatch::makeTriSf
void makeTriSf() const
Make triangular surface face area vectors.
Definition: immersedBoundaryFvPatch.C:1922
Foam::GeometricField::internalField
InternalField & internalField()
Return internal field.
Definition: GeometricField.C:724
Foam::HashTable::erase
bool erase(const iterator &)
Erase a hashedEntry specified by given iterator.
Foam::immersedBoundaryFvPatch::ibDelta
const scalarField & ibDelta() const
Return distance to IB.
Definition: immersedBoundaryFvPatch.C:2535
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:52
Foam::DynamicList::shrink
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:258
Foam::pow
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Definition: dimensionedScalar.C:73
Foam::immersedBoundaryFvPatch::distFactor_
static const debug::tolerancesSwitch distFactor_
Sampling point distance factor.
Definition: immersedBoundaryFvPatch.H:98
fvBoundaryMesh.H
Foam::FatalError
error FatalError
Foam::immersedBoundaryFvPatch::triCf
const vectorField & triCf() const
Return triangular surface face centres.
Definition: immersedBoundaryFvPatch.C:2569
Foam::immersedBoundaryFvPatch::ibMagSf
const scalarField & ibMagSf() const
Return IB face area vector magnitudes.
Definition: immersedBoundaryFvPatch.C:2524
Foam::SortableList
A list that is sorted upon construction or when explicitly requested with the sort() method.
Definition: List.H:65
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::dimensioned
Generic dimensioned Type class.
Definition: dimensionedScalarFwd.H:41
Foam::C::C
C()
Construct null.
Definition: C.C:41
Foam::HashTable::found
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::cellSet
A collection of cell labels.
Definition: cellSet.H:48
Foam::boolList
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
Foam::immersedBoundaryFvPatch::makeIbPointsAndNormals
void makeIbPointsAndNormals() const
Make immersed boundary points and normals.
Definition: immersedBoundaryFvPatch.C:946
Foam::immersedBoundaryFvPatch::gammaExt
const volScalarField & gammaExt() const
Get extended flud cells indicator, including live and IB cells.
Definition: immersedBoundaryFvPatch.C:2267
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::immersedBoundaryFvPatch::makeIbCellCells
void makeIbCellCells() const
Make extended IB cells stencils.
Definition: immersedBoundaryFvPatch.C:1065
Foam::immersedBoundaryFvPatch::ibInternalFaces
const labelList & ibInternalFaces() const
Return list of internal faces in the region bounded by IB faces.
Definition: immersedBoundaryFvPatch.C:2344
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:405
Foam::immersedBoundaryFvPatch::ibFaceFlips
const boolList & ibFaceFlips() const
Return list of IB face flip:
Definition: immersedBoundaryFvPatch.C:2322
Foam::immersedBoundaryFvPatch::makeIbInternalFaces
void makeIbInternalFaces() const
Make internal IB faces.
Definition: immersedBoundaryFvPatch.C:852
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
Foam::immersedBoundaryFvPatch::ibCellCells
const labelListList & ibCellCells() const
Return IB cell extended stencil.
Definition: immersedBoundaryFvPatch.C:2400
Foam::immersedBoundaryFvPatch::ibNormals
const vectorField & ibNormals() const
Return IB normals.
Definition: immersedBoundaryFvPatch.C:2366
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::immersedBoundaryFvPatch::angleFactor_
static const debug::tolerancesSwitch angleFactor_
Fitting angle rejection factor (deg)
Definition: immersedBoundaryFvPatch.H:86
Foam::surfaceScalarField
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Definition: surfaceFieldsFwd.H:52
Foam::Vector< scalar >
Foam::Time::timeName
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:741
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:142
Foam::immersedBoundaryFvPatch::deadFaces
const labelList & deadFaces() const
Return dead faces.
Definition: immersedBoundaryFvPatch.C:2480
Foam::immersedBoundaryFvPatch::makeIbCells
void makeIbCells() const
Make list of cells next to immersed boundary.
Definition: immersedBoundaryFvPatch.C:371
Foam::immersedBoundaryFvPatch::radiusFactor_
static const debug::tolerancesSwitch radiusFactor_
Fitting radius factor.
Definition: immersedBoundaryFvPatch.H:90
Foam::immersedBoundaryFvPatch::deadCellsExt
const labelList & deadCellsExt() const
Return extended dead cells.
Definition: immersedBoundaryFvPatch.C:2469
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
Foam::immersedBoundaryFvPatch::makeIbFaces
void makeIbFaces() const
Make IB faces.
Definition: immersedBoundaryFvPatch.C:642
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:333
Foam::direction
unsigned char direction
Definition: direction.H:43
Foam::SortableList::indices
const labelList & indices() const
Return the list of sorted indices. Updated every sort.
Definition: SortableList.H:90
Foam::immersedBoundaryFvPatch::ibInsideFaces
const labelList & ibInsideFaces() const
Return list of fluid faces for which one neighbour is an.
Definition: immersedBoundaryFvPatch.C:2333
Foam::immersedBoundaryFvPatch::makeIbInsideFaces
void makeIbInsideFaces() const
Make inside IB faces.
Definition: immersedBoundaryFvPatch.C:765
Foam::immersedBoundaryFvPatch::makeLiveCells
void makeLiveCells() const
Make list of live cells.
Definition: immersedBoundaryFvPatch.C:1745
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:243
Foam::immersedBoundaryFvPatch::ibPoints
const vectorField & ibPoints() const
Return IB points.
Definition: immersedBoundaryFvPatch.C:2355
Foam::immersedBoundaryFvPatch::findCellCells
void findCellCells(const vector &pt, const label cellID, labelList &cellCells) const
Return extended cell-cell addressing.
Definition: immersedBoundaryFvPatch.C:1992
immersedBoundaryFvPatch.H
Foam::IPstream
Input inter-processor communications stream.
Definition: IPstream.H:50
FatalErrorIn
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:313
WarningIn
#define WarningIn(functionName)
Report a warning using Foam::Warning.
Definition: messageStream.H:254
Foam::sort
void sort(UList< T > &)
Definition: UList.C:107
Foam::immersedBoundaryFvPatch::cellSize
scalar cellSize(label cellID) const
Calc cell size.
Definition: immersedBoundaryFvPatch.C:2086
Foam::immersedBoundaryFvPatch::makeIbDelta
void makeIbDelta() const
Make distance between IB cell centres.
Definition: immersedBoundaryFvPatch.C:1868
Foam::immersedBoundaryFvPatch::ibProcCells
const labelListList & ibProcCells() const
Return neighbour proc cells.
Definition: immersedBoundaryFvPatch.C:2447
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::immersedBoundaryFvPatch::makeIbCellSizes
void makeIbCellSizes() const
Make immersed boundary cell sizes.
Definition: immersedBoundaryFvPatch.C:1779
Foam::UList::size
label size() const
Return the number of elements in the UList.
Definition: UListI.H:299
Foam::C
Graphite solid properties.
Definition: C.H:57
Foam::GeometricField
Generic GeometricField class.
Definition: surfaceFieldsFwd.H:52
Foam::immersedBoundaryFvPatch::makeIbSamplingPointDelta
void makeIbSamplingPointDelta() const
Make distance between IB cell centres.
Definition: immersedBoundaryFvPatch.C:1894
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::GeometricField::GeometricBoundaryField
Definition: GeometricField.H:105
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Foam::immersedBoundaryFvPatch::ibProcCentres
const FieldField< Field, vector > & ibProcCentres() const
Return neighbour proc centres.
Definition: immersedBoundaryFvPatch.C:2412