meshRefinementBlock.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) 2018-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 it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "meshRefinement.H"
29 #include "fvMesh.H"
30 #include "Time.H"
31 #include "refinementSurfaces.H"
32 #include "removeCells.H"
33 #include "unitConversion.H"
34 #include "bitSet.H"
35 
36 #include "FaceCellWave.H"
37 #include "volFields.H"
38 #include "wallPoints.H"
39 #include "searchableSurfaces.H"
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
44 //Foam::label Foam::meshRefinement::markFakeGapRefinement
45 //(
46 // const scalar planarCos,
47 //
48 // const label nAllowRefine,
49 // const labelList& neiLevel,
50 // const pointField& neiCc,
51 //
52 // labelList& refineCell,
53 // label& nRefine
54 //) const
55 //{
56 // label oldNRefine = nRefine;
57 //
58 //
59 // // Collect candidate faces (i.e. intersecting any surface and
60 // // owner/neighbour not yet refined.
61 // const labelList testFaces(getRefineCandidateFaces(refineCell));
62 //
63 // // Collect segments
64 // pointField start(testFaces.size());
65 // pointField end(testFaces.size());
66 // labelList minLevel(testFaces.size());
67 //
68 // calcCellCellRays
69 // (
70 // neiCc,
71 // neiLevel,
72 // testFaces,
73 // start,
74 // end,
75 // minLevel
76 // );
77 //
78 //
79 // // Re-use the gap shooting methods. This needs:
80 // // - shell gapLevel : faked. Set to 0,labelMax
81 // // - surface gapLevel : faked by overwriting
82 //
83 //
84 // List<FixedList<label, 3>>& surfGapLevel = const_cast
85 // <
86 // List<FixedList<label, 3>>&
87 // >(surfaces_.extendedGapLevel());
88 //
89 // List<volumeType>& surfGapMode = const_cast
90 // <
91 // List<volumeType>&
92 // >(surfaces_.extendedGapMode());
93 //
94 // const List<FixedList<label, 3>> surfOldLevel(surfGapLevel);
95 // const List<volumeType> surfOldMode(surfGapMode);
96 //
97 // // Set the extended gap levels
98 // forAll(surfaces_.gapLevel(), regioni)
99 // {
100 // surfGapLevel[regioni] = FixedList<label, 3>
101 // ({
102 // 3,
103 // -1,
104 // surfaces_.gapLevel()[regioni]+1
105 // });
106 // }
107 // surfGapMode = volumeType::MIXED;
108 //
109 //Pout<< "gapLevel was:" << surfOldLevel << endl;
110 //Pout<< "gapLevel now:" << surfGapLevel << endl;
111 //Pout<< "gapMode was:" << surfOldMode << endl;
112 //Pout<< "gapMode now:" << surfGapMode << endl;
113 //Pout<< "nRefine was:" << oldNRefine << endl;
114 //
115 //
116 //
117 // List<List<FixedList<label, 3>>>& shellGapLevel = const_cast
118 // <
119 // List<List<FixedList<label, 3>>>&
120 // >(shells_.extendedGapLevel());
121 //
122 // List<List<volumeType>>& shellGapMode = const_cast
123 // <
124 // List<List<volumeType>>&
125 // >(shells_.extendedGapMode());
126 //
127 // const List<List<FixedList<label, 3>>> shellOldLevel(shellGapLevel);
128 // const List<List<volumeType>> shellOldMode(shellGapMode);
129 //
130 // // Set the extended gap levels
131 // forAll(shellGapLevel, shelli)
132 // {
133 // shellGapLevel[shelli] = FixedList<label, 3>({3, -1, labelMax});
134 // shellGapMode[shelli] = volumeType::MIXED;
135 // }
136 //Pout<< "shellLevel was:" << shellOldLevel << endl;
137 //Pout<< "shellLevel now:" << shellGapLevel << endl;
138 //
139 // const label nAdditionalRefined = markSurfaceGapRefinement
140 // (
141 // planarCos,
142 //
143 // nAllowRefine,
144 // neiLevel,
145 // neiCc,
146 //
147 // refineCell,
148 // nRefine
149 // );
150 //
151 //Pout<< "nRefine now:" << nRefine << endl;
152 //
153 // // Restore
154 // surfGapLevel = surfOldLevel;
155 // surfGapMode = surfOldMode;
156 // shellGapLevel = shellOldLevel;
157 // shellGapMode = shellOldMode;
158 //
159 // return nAdditionalRefined;
160 //}
161 
162 
164 (
165  const labelList& cellLevel,
166  const labelList& neiLevel,
167  const labelList& refineCell,
168  bitSet& isOutsideFace
169 ) const
170 {
171  // Get faces:
172  // - on outside of cell set
173  // - inbetween same cell level (i.e. quads)
174 
175  isOutsideFace.setSize(mesh_.nFaces());
176  isOutsideFace = Zero;
177 
178  forAll(mesh_.faceNeighbour(), facei)
179  {
180  label own = mesh_.faceOwner()[facei];
181  label nei = mesh_.faceNeighbour()[facei];
182  if
183  (
184  (cellLevel[own] == cellLevel[nei])
185  && (
186  (refineCell[own] != -1)
187  != (refineCell[nei] != -1)
188  )
189  )
190  {
191  isOutsideFace.set(facei);
192  }
193  }
194  {
195 
196  const label nBnd = mesh_.nFaces()-mesh_.nInternalFaces();
197 
198  labelList neiRefineCell(nBnd);
199  syncTools::swapBoundaryCellList(mesh_, refineCell, neiRefineCell);
200  for (label bFacei = 0; bFacei < nBnd; ++bFacei)
201  {
202  label facei = mesh_.nInternalFaces()+bFacei;
203  label own = mesh_.faceOwner()[facei];
204 
205  if
206  (
207  (cellLevel[own] == neiLevel[bFacei])
208  && (
209  (refineCell[own] != -1)
210  != (neiRefineCell[bFacei] != -1)
211  )
212  )
213  {
214  isOutsideFace.set(facei);
215  }
216  }
217  }
218 }
219 
220 
222 (
223  const bitSet& isOutsideFace,
224  const label celli
225 ) const
226 {
227  const cell& cFaces = mesh_.cells()[celli];
228  const vectorField& faceAreas = mesh_.faceAreas();
229 
230  Vector<bool> haveDirs(vector::uniform(false));
231 
232  forAll(cFaces, cFacei)
233  {
234  const label facei = cFaces[cFacei];
235 
236  if (isOutsideFace[facei])
237  {
238  const vector& n = faceAreas[facei];
239  scalar magSqrN = magSqr(n);
240 
241  if (magSqrN > ROOTVSMALL)
242  {
243  for
244  (
245  direction dir = 0;
246  dir < pTraits<vector>::nComponents;
247  dir++
248  )
249  {
250  if (Foam::sqr(n[dir]) > 0.99*magSqrN)
251  {
252  haveDirs[dir] = true;
253  break;
254  }
255  }
256  }
257  }
258  }
259 
260  label nDirs = 0;
261  forAll(haveDirs, dir)
262  {
263  if (haveDirs[dir])
264  {
265  nDirs++;
266  }
267  }
268  return nDirs;
269 }
270 
271 
273 (
274  const labelList& neiLevel,
275  const bitSet& isOutsideFace,
277  label& nRefine
278 ) const
279 {
280  // Get cells with three or more outside faces
281  const cellList& cells = mesh_.cells();
282  forAll(cells, celli)
283  {
284  if (refineCell[celli] == -1)
285  {
286  if (countFaceDirs(isOutsideFace, celli) == 3)
287  {
288  // Mark cell with any value
289  refineCell[celli] = 0;
290  nRefine++;
291  }
292  }
293  }
294 }
295 
296 
297 void Foam::meshRefinement::markMultiRegionCell
298 (
299  const label celli,
300  const FixedList<label, 3>& surface,
301 
302  Map<FixedList<label, 3>>& cellToRegions,
303  bitSet& isMultiRegion
304 ) const
305 {
306  if (!isMultiRegion[celli])
307  {
308  Map<FixedList<label, 3>>::iterator fnd = cellToRegions.find(celli);
309  if (!fnd.found())
310  {
311  cellToRegions.insert(celli, surface);
312  }
313  else if (fnd() != surface)
314  {
315  // Found multiple intersections on cell
316  isMultiRegion.set(celli);
317  }
318  }
319 }
320 
321 
322 void Foam::meshRefinement::detectMultiRegionCells
323 (
324  const labelListList& faceZones,
325  const labelList& testFaces,
326 
327  const labelList& surface1,
328  const List<pointIndexHit>& hit1,
329  const labelList& region1,
330 
331  const labelList& surface2,
332  const List<pointIndexHit>& hit2,
333  const labelList& region2,
334 
335  bitSet& isMultiRegion
336 ) const
337 {
338  isMultiRegion.clear();
339  isMultiRegion.setSize(mesh_.nCells());
340 
341  Map<FixedList<label, 3>> cellToRegions(testFaces.size());
342 
343  forAll(testFaces, i)
344  {
345  const pointIndexHit& info1 = hit1[i];
346  if (info1.hit())
347  {
348  const label facei = testFaces[i];
349  const labelList& fz1 = faceZones[surface1[i]];
350  const FixedList<label, 3> surfaceInfo1
351  ({
352  surface1[i],
353  region1[i],
354  (fz1.size() ? fz1[info1.index()] : region1[i])
355  });
356 
357  markMultiRegionCell
358  (
359  mesh_.faceOwner()[facei],
360  surfaceInfo1,
361  cellToRegions,
362  isMultiRegion
363  );
364  if (mesh_.isInternalFace(facei))
365  {
366  markMultiRegionCell
367  (
368  mesh_.faceNeighbour()[facei],
369  surfaceInfo1,
370  cellToRegions,
371  isMultiRegion
372  );
373  }
374 
375  const pointIndexHit& info2 = hit2[i];
376 
377  if (info2.hit() && info1 != info2)
378  {
379  const labelList& fz2 = faceZones[surface2[i]];
380  const FixedList<label, 3> surfaceInfo2
381  ({
382  surface2[i],
383  region2[i],
384  (fz2.size() ? fz2[info2.index()] : region2[i])
385  });
386 
387  markMultiRegionCell
388  (
389  mesh_.faceOwner()[facei],
390  surfaceInfo2,
391  cellToRegions,
392  isMultiRegion
393  );
394  if (mesh_.isInternalFace(facei))
395  {
396  markMultiRegionCell
397  (
398  mesh_.faceNeighbour()[facei],
399  surfaceInfo2,
400  cellToRegions,
401  isMultiRegion
402  );
403  }
404  }
405  }
406  }
407 
408 
410  {
411  volScalarField multiCell
412  (
413  IOobject
414  (
415  "multiCell",
416  mesh_.time().timeName(),
417  mesh_,
420  false
421  ),
422  mesh_,
424  (
425  "zero",
426  dimensionSet(0, 1, 0, 0, 0),
427  0.0
428  )
429  );
430  forAll(isMultiRegion, celli)
431  {
432  if (isMultiRegion[celli])
433  {
434  multiCell[celli] = 1.0;
435  }
436  }
437 
438  Info<< "Writing all multi cells to " << multiCell.name() << endl;
439  multiCell.write();
440  }
441 }
442 
443 
444 Foam::label Foam::meshRefinement::markProximityRefinementWave
445 (
446  const scalar planarCos,
447  const labelList& blockedSurfaces,
448  const label nAllowRefine,
449  const labelList& neiLevel,
450  const pointField& neiCc,
451 
452  labelList& refineCell,
453  label& nRefine
454 ) const
455 {
456  labelListList faceZones(surfaces_.surfaces().size());
457  {
458  // If triSurface do additional zoning based on connectivity
459  for (const label surfi : blockedSurfaces)
460  {
461  const label geomi = surfaces_.surfaces()[surfi];
462  const searchableSurface& s = surfaces_.geometry()[geomi];
463  if (isA<triSurfaceMesh>(s) && !isA<distributedTriSurfaceMesh>(s))
464  {
465  const triSurfaceMesh& surf = refCast<const triSurfaceMesh>(s);
466  const labelListList& edFaces = surf.edgeFaces();
467  boolList isOpenEdge(edFaces.size(), false);
468  forAll(edFaces, i)
469  {
470  if (edFaces[i].size() == 1)
471  {
472  isOpenEdge[i] = true;
473  }
474  }
475 
476  labelList faceZone;
477  const label nZones = surf.markZones(isOpenEdge, faceZone);
478  if (nZones > 1)
479  {
480  faceZones[surfi].transfer(faceZone);
481  }
482  }
483  }
484  }
485 
486 
487  // Re-work the blockLevel of the blockedSurfaces into a length scale
488  // and a number of cells to cross
489  scalarField regionToBlockSize(surfaces_.blockLevel().size(), 0);
490  //label nIters = 2;
491 
492  for (const label surfi : blockedSurfaces)
493  {
494  const label geomi = surfaces_.surfaces()[surfi];
495  const searchableSurface& s = surfaces_.geometry()[geomi];
496  const label nRegions = s.regions().size();
497  for (label regioni = 0; regioni < nRegions; regioni++)
498  {
499  const label globalRegioni = surfaces_.globalRegion(surfi, regioni);
500  const label bLevel = surfaces_.blockLevel()[globalRegioni];
501  regionToBlockSize[globalRegioni] =
502  meshCutter_.level0EdgeLength()/pow(2.0, bLevel);
503 
504  //const label mLevel = surfaces_.maxLevel()[globalRegioni];
508  //if (isA<triSurfaceMesh>(s) && !isA<distributedTriSurfaceMesh>(s))
509  //{
510  // const triSurfaceMesh& surf = refCast<const triSurfaceMesh>(s);
511  //}
512 
513  //nIters = max(nIters, (2<<(mLevel-bLevel)));
514  }
515  }
516  // Clever limiting of the number of iterations (= max cells in the channel)
517  // since it has too many problematic issues, e.g. with volume refinement.
518  // Since the real check uses the proper distance anyway just disable.
519  const label nIters = mesh_.globalData().nTotalCells();
520 
521 
522  // Collect candidate faces (i.e. intersecting any surface and
523  // owner/neighbour not yet refined)
524  const labelList testFaces(getRefineCandidateFaces(refineCell));
525 
526  // Collect segments
527  pointField start(testFaces.size());
528  pointField end(testFaces.size());
529  labelList minLevel(testFaces.size());
530 
531  calcCellCellRays
532  (
533  neiCc,
534  neiLevel,
535  testFaces,
536  start,
537  end,
538  minLevel
539  );
540  // TBD. correct nIters for actual cellLevel (since e.g. volume refinement
541  // might add to cell level). Unfortunately we only have minLevel,
542  // not maxLevel. Problem: what if volume refinement only in middle of
543  // channel? Workaround: have dummy surface with e.g. maxLevel 100 to
544  // force nIters to be high enough.
545 
546 
547  // Test for all intersections (with surfaces of higher gap level than
548  // minLevel) and cache per cell the max surface level and the local normal
549  // on that surface.
550 
551  labelList surface1;
552  List<pointIndexHit> hit1;
553  labelList region1;
554  vectorField normal1;
555 
556  labelList surface2;
557  List<pointIndexHit> hit2;
558  labelList region2;
559  vectorField normal2;
560 
561  surfaces_.findNearestIntersection
562  (
563  blockedSurfaces,
564  start,
565  end,
566 
567  surface1,
568  hit1,
569  region1, // local region
570  normal1,
571 
572  surface2,
573  hit2,
574  region2, // local region
575  normal2
576  );
577 
578 
579  // Detect cells that are using multiple surface regions
580  bitSet isMultiRegion;
581  detectMultiRegionCells
582  (
583  faceZones,
584  testFaces,
585 
586  surface1,
587  hit1,
588  region1,
589 
590  surface2,
591  hit2,
592  region2,
593 
594  isMultiRegion
595  );
596 
597 
598  label n = 0;
599  forAll(testFaces, i)
600  {
601  if (hit1[i].hit())
602  {
603  n++;
604  }
605  }
606 
607  List<wallPoints> faceDist(n);
608  labelList changedFaces(n);
609  n = 0;
610 
611  DynamicList<point> originLocation(2);
612  DynamicList<scalar> originDistSqr(2);
613  DynamicList<FixedList<label, 3>> originSurface(2);
614  //DynamicList<point> originNormal(2);
615 
616  forAll(testFaces, i)
617  {
618  if (hit1[i].hit())
619  {
620  const label facei = testFaces[i];
621  const point& fc = mesh_.faceCentres()[facei];
622  const labelList& fz1 = faceZones[surface1[i]];
623 
624  originLocation.clear();
625  originDistSqr.clear();
626  //originNormal.clear();
627  originSurface.clear();
628 
629  originLocation.append(hit1[i].hitPoint());
630  originDistSqr.append(magSqr(fc-hit1[i].hitPoint()));
631  //originNormal.append(normal1[i]);
632  originSurface.append
633  (
634  FixedList<label, 3>
635  ({
636  surface1[i],
637  region1[i],
638  (fz1.size() ? fz1[hit1[i].index()] : region1[i])
639  })
640  );
641 
642  if (hit2[i].hit() && hit1[i] != hit2[i])
643  {
644  const labelList& fz2 = faceZones[surface2[i]];
645  originLocation.append(hit2[i].hitPoint());
646  originDistSqr.append(magSqr(fc-hit2[i].hitPoint()));
647  //originNormal.append(normal2[i]);
648  originSurface.append
649  (
650  FixedList<label, 3>
651  ({
652  surface2[i],
653  region2[i],
654  (fz2.size() ? fz2[hit2[i].index()] : region2[i])
655  })
656  );
657  }
658 
659  faceDist[n] = wallPoints
660  (
661  originLocation, // origin
662  originDistSqr, // distance to origin
663  originSurface // surface+region+zone
664  //originNormal // normal at origin
665  );
666  changedFaces[n] = facei;
667  n++;
668  }
669  }
670 
671 
672  // Clear intersection info
673  surface1.clear();
674  hit1.clear();
675  region1.clear();
676  normal1.clear();
677  surface2.clear();
678  hit2.clear();
679  region2.clear();
680  normal2.clear();
681 
682 
683  List<wallPoints> allFaceInfo(mesh_.nFaces());
684  List<wallPoints> allCellInfo(mesh_.nCells());
685 
686  FaceCellWave<wallPoints> wallDistCalc
687  (
688  mesh_,
689  changedFaces,
690  faceDist,
691  allFaceInfo,
692  allCellInfo,
693  0 // max iterations
694  );
695  wallDistCalc.iterate(nIters);
696 
697 
699  {
700  // Dump current nearest opposite surfaces
702  (
703  IOobject
704  (
705  "gapSize",
706  mesh_.time().timeName(),
707  mesh_,
710  false
711  ),
712  mesh_,
714  (
715  "zero",
716  dimLength, //dimensionSet(0, 1, 0, 0, 0),
717  -1
718  )
719  );
720 
721  forAll(allCellInfo, celli)
722  {
723  if (allCellInfo[celli].valid(wallDistCalc.data()))
724  {
725  const point& cc = mesh_.C()[celli];
726  // Nearest surface points
727  const List<point>& origin = allCellInfo[celli].origin();
728 
729  // Find 'opposite' pair with minimum distance
730  for (label i = 0; i < origin.size(); i++)
731  {
732  for (label j = i + 1; j < origin.size(); j++)
733  {
734  if (((cc-origin[i]) & (cc-origin[j])) < 0)
735  {
736  const scalar d(mag(origin[i]-origin[j]));
737  if (distance[celli] < 0)
738  {
739  distance[celli] = d;
740  }
741  else
742  {
743  distance[celli] = min(distance[celli], d);
744  }
745  }
746  }
747  }
748  }
749  }
750  distance.correctBoundaryConditions();
751 
752  Info<< "Writing measured gap distance to "
753  << distance.name() << endl;
754  distance.write();
755  }
756 
757 
758 
759  // Detect tight gaps:
760  // - cell is inbetween the two surfaces
761  // - two surfaces are planarish
762  // - two surfaces are not too far apart
763  // (number of walking iterations is a too-coarse measure)
764 
765  scalarField smallGapDistance(mesh_.nCells(), 0.0);
766  label nMulti = 0;
767  label nSmallGap = 0;
768 
769  //OBJstream str(mesh_.time().timePath()/"multiRegion.obj");
770 
771 
772  forAll(allCellInfo, celli)
773  {
774  if (allCellInfo[celli].valid(wallDistCalc.data()))
775  {
776  const point& cc = mesh_.C()[celli];
777 
778  const List<point>& origin = allCellInfo[celli].origin();
779  const List<FixedList<label, 3>>& surface =
780  allCellInfo[celli].surface();
781 
782  // Find pair with minimum distance
783  for (label i = 0; i < origin.size(); i++)
784  {
785  for (label j = i + 1; j < origin.size(); j++)
786  {
787  scalar maxDist
788  (
789  max
790  (
791  mag(cc-origin[i]),
792  mag(cc-origin[j])
793  )
794  );
795 
796  //if (isMultiRegion[celli])
797  //{
798  // // The intersection locations are too inaccurate
799  // // (since not proper nearest, just a cell-cell ray
800  // // intersection) so include always
801  //
802  // smallGapDistance[celli] =
803  // max(smallGapDistance[celli], maxDist);
804  //
805  //
806  // str.write(linePointRef(cc, origin[i]));
807  // str.write(linePointRef(cc, origin[j]));
808  //
809  // nMulti++;
810  //}
811  //else
812  if (((cc-origin[i]) & (cc-origin[j])) < 0)
813  {
814  const label globalRegioni = surfaces_.globalRegion
815  (
816  surface[i][0],
817  surface[i][1]
818  );
819  const label globalRegionj = surfaces_.globalRegion
820  (
821  surface[j][0],
822  surface[j][1]
823  );
824 
825  const scalar maxSize = max
826  (
827  regionToBlockSize[globalRegioni],
828  regionToBlockSize[globalRegionj]
829  );
830 
831  if
832  (
833  magSqr(origin[i]-origin[j])
834  < Foam::sqr(2*maxSize)
835  )
836  {
837  smallGapDistance[celli] =
838  max(smallGapDistance[celli], maxDist);
839  nSmallGap++;
840  }
841  }
842  }
843  }
844  }
845  }
846 
847 
848  if (debug)
849  {
850  Info<< "Marked for blocking due to intersecting multiple surfaces : "
851  << returnReduce(nMulti, sumOp<label>()) << " cells." << endl;
852  Info<< "Marked for blocking due to close opposite surfaces : "
853  << returnReduce(nSmallGap, sumOp<label>()) << " cells." << endl;
854  }
855 
857  {
859  (
860  IOobject
861  (
862  "smallGapDistance",
863  mesh_.time().timeName(),
864  mesh_,
867  false
868  ),
869  mesh_,
871  (
872  "zero",
873  dimensionSet(0, 1, 0, 0, 0),
874  0.0
875  )
876  );
877  distance.field() = smallGapDistance;
878  distance.correctBoundaryConditions();
879 
880  Info<< "Writing all small-gap cells to "
881  << distance.name() << endl;
882  distance.write();
883  }
884 
885 
886  // Mark refinement
887  const label oldNRefine = nRefine;
888  forAll(smallGapDistance, celli)
889  {
890  if (smallGapDistance[celli] > SMALL)
891  {
892  if
893  (
894  !markForRefine
895  (
896  0, // mark level
897  nAllowRefine,
898  refineCell[celli],
899  nRefine
900  )
901  )
902  {
903  if (debug)
904  {
905  Pout<< "Stopped refining since reaching my cell"
906  << " limit of " << mesh_.nCells()+7*nRefine
907  << endl;
908  }
909  break;
910  }
911  }
912  }
913 
914  if
915  (
916  returnReduce(nRefine, sumOp<label>())
917  > returnReduce(nAllowRefine, sumOp<label>())
918  )
919  {
920  Info<< "Reached refinement limit." << endl;
921  }
922 
923  return returnReduce(nRefine-oldNRefine, sumOp<label>());
924 }
925 
926 
928 (
929  const scalar planarAngle,
930  const labelList& minSurfaceLevel,
931  const labelList& globalToMasterPatch,
932  const label growIter
933 )
934 {
935  // Swap neighbouring cell centres and cell level
936  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
937  pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
938  calcNeighbourData(neiLevel, neiCc);
939 
940  labelList refineCell(mesh_.nCells(), -1);
941  label nRefine = 0;
942  //markProximityRefinement
943  //(
944  // Foam::cos(degToRad(planarAngle)),
945  //
946  // minSurfaceLevel, // surface min level
947  // labelList(minSurfaceLevel.size(), labelMax), // surfaceGapLevel
948  //
949  // labelMax/Pstream::nProcs(), //nAllowRefine,
950  // neiLevel,
951  // neiCc,
952  //
953  // refineCell,
954  // nRefine
955  //);
956 
957 
958  // Determine minimum blockLevel per surface
959  Map<label> surfToBlockLevel;
960 
961  forAll(surfaces_.surfaces(), surfi)
962  {
963  const label geomi = surfaces_.surfaces()[surfi];
964  const searchableSurface& s = surfaces_.geometry()[geomi];
965  const label nRegions = s.regions().size();
966 
967  label minBlockLevel = labelMax;
968  for (label regioni = 0; regioni < nRegions; regioni++)
969  {
970  const label globalRegioni = surfaces_.globalRegion(surfi, regioni);
971  minBlockLevel = min
972  (
973  minBlockLevel,
974  surfaces_.blockLevel()[globalRegioni]
975  );
976  }
977 
978  if (minBlockLevel < labelMax)
979  {
980  surfToBlockLevel.insert(surfi, minBlockLevel);
981  }
982  }
983 
984 
985  markProximityRefinementWave
986  (
987  Foam::cos(degToRad(planarAngle)),
988  surfToBlockLevel.sortedToc(),
989 
990  labelMax/Pstream::nProcs(), //nAllowRefine,
991  neiLevel,
992  neiCc,
993 
994  refineCell,
995  nRefine
996  );
997 
998 
1000  //markFakeGapRefinement
1001  //(
1002  // Foam::cos(degToRad(planarAngle)),
1003  //
1004  // labelMax/Pstream::nProcs(), //nAllowRefine,
1005  // neiLevel,
1006  // neiCc,
1007  //
1008  // refineCell,
1009  // nRefine
1010  //);
1011 
1012 
1013  Info<< "Marked for blocking due to close opposite surfaces : "
1014  << returnReduce(nRefine, sumOp<label>()) << " cells." << endl;
1015 
1016  // Remove outliers, i.e. cells with all points exposed
1017  if (growIter)
1018  {
1019  labelList oldRefineCell(refineCell);
1020 
1021  // Pass1: extend the set to fill in gaps
1022  bitSet isOutsideFace;
1023  for (label iter = 0; iter < growIter; iter++)
1024  {
1025  // Get outside faces
1026  markOutsideFaces
1027  (
1028  meshCutter_.cellLevel(),
1029  neiLevel,
1030  refineCell,
1031  isOutsideFace
1032  );
1033  // Extend with cells with three outside faces
1034  growSet(neiLevel, isOutsideFace, refineCell, nRefine);
1035  }
1036 
1037 
1038  // Pass2: erode back to original set if pass1 didn't help
1039  for (label iter = 0; iter < growIter; iter++)
1040  {
1041  // Get outside faces. Ignore cell level.
1042  markOutsideFaces
1043  (
1044  labelList(mesh_.nCells(), 0),
1045  labelList(neiLevel.size(), 0),
1046  refineCell,
1047  isOutsideFace
1048  );
1049 
1050  // Unmark cells with three or more outside faces
1051  for (label celli = 0; celli < mesh_.nCells(); celli++)
1052  {
1053  if (refineCell[celli] != -1 && oldRefineCell[celli] == -1)
1054  {
1055  if (countFaceDirs(isOutsideFace, celli) >= 3)
1056  {
1057  refineCell[celli] = -1;
1058  --nRefine;
1059  }
1060  }
1061  }
1062  }
1063 
1064  Info<< "Marked for blocking after filtering : "
1065  << returnReduce(nRefine, sumOp<label>()) << " cells." << endl;
1066  }
1067 
1068 
1069  // Determine patch for every mesh face
1070  const PtrList<surfaceZonesInfo>& surfZones = surfaces_.surfZones();
1071  labelList unnamedSurfaces(surfaceZonesInfo::getUnnamedSurfaces(surfZones));
1072  const label defaultRegion(surfaces_.globalRegion(unnamedSurfaces[0], 0));
1073 
1074  const labelList nearestRegion
1075  (
1076  nearestIntersection
1077  (
1078  unnamedSurfaces,
1079  defaultRegion
1080  )
1081  );
1082 
1083  // Pack
1084  labelList cellsToRemove(nRefine);
1085  nRefine = 0;
1086 
1087  forAll(refineCell, cellI)
1088  {
1089  if (refineCell[cellI] != -1)
1090  {
1091  cellsToRemove[nRefine++] = cellI;
1092  }
1093  }
1094 
1095  // Remove cells
1096  removeCells cellRemover(mesh_);
1097  labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
1098 
1099  labelList exposedPatches(exposedFaces.size());
1100  forAll(exposedFaces, i)
1101  {
1102  label facei = exposedFaces[i];
1103  exposedPatches[i] = globalToMasterPatch[nearestRegion[facei]];
1104  }
1105 
1106  return doRemoveCells
1107  (
1108  cellsToRemove,
1109  exposedFaces,
1110  exposedPatches,
1111  cellRemover
1112  );
1113 }
1114 
1115 
1116 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
nZones
label nZones
Definition: interpolatedFaces.H:24
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
volFields.H
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::meshRefinement::removeGapCells
autoPtr< mapPolyMesh > removeGapCells(const scalar planarAngle, const labelList &minSurfaceLevel, const labelList &globalToMasterPatch, const label growIter)
Detect gapRefinement cells and remove them.
Definition: meshRefinementBlock.C:928
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
distributedTriSurfaceMesh.H
Foam::labelMax
constexpr label labelMax
Definition: label.H:61
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::PackedList::setSize
void setSize(const label len, unsigned int val=0u)
Alias for resize()
Definition: PackedList.H:521
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::dimLength
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:53
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::removeCells
Given list of cells to remove, insert all the topology changes.
Definition: removeCells.H:63
Foam::meshRefinement::countFaceDirs
label countFaceDirs(const bitSet &isOutsideFace, const label celli) const
Count number of faces on cell that are in set.
Definition: meshRefinementBlock.C:222
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:574
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: lumpedPointController.H:69
unitConversion.H
Unit conversion functions.
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:69
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:350
removeCells.H
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
bitSet.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::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Foam::meshRefinement::growSet
void growSet(const labelList &neiLevel, const bitSet &isOutsideFace, labelList &refineCell, label &nRefine) const
Add one layer of cells to set.
Definition: meshRefinementBlock.C:273
searchableSurfaces.H
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::Field< vector >
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
refinementSurfaces.H
Foam::searchableSurface
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
Definition: searchableSurface.H:69
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:43
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:62
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
Foam::pow
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Definition: dimensionedScalar.C:75
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
meshRefinement.H
wallPoints.H
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:121
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
fvMesh.H
Foam::degToRad
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Definition: unitConversion.H:48
Foam::distance
scalar distance(const vector &p1, const vector &p2)
Definition: curveTools.C:12
Foam::surfaceZonesInfo::getUnnamedSurfaces
static labelList getUnnamedSurfaces(const PtrList< surfaceZonesInfo > &surfList)
Get indices of unnamed surfaces (surfaces without faceZoneName)
Definition: surfaceZonesInfo.C:242
Time.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::refineCell
Container with cells to refine. Refinement given as single direction.
Definition: refineCell.H:56
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
A PointIndexHit for 3D points.
Definition: pointIndexHit.H:46
Foam::Vector
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:62
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::FixedList< label, 3 >
FaceCellWave.H
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:115
Foam::direction
uint8_t direction
Definition: direction.H:52
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::meshRefinement::markOutsideFaces
void markOutsideFaces(const labelList &cellLevel, const labelList &neiLevel, const labelList &refineCell, bitSet &isOutsideFace) const
Mark faces on interface between set and rest.
Definition: meshRefinementBlock.C:164
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::IOobject::NO_READ
Definition: IOobject.H:123
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::meshRefinement::MESH
Definition: meshRefinement.H:94
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Number of processes in parallel run, and 1 for serial run.
Definition: UPstream.H:446
Foam::removeCells::getExposedFaces
labelList getExposedFaces(const bitSet &removedCell) const
Get labels of faces exposed after cells removal.
Definition: removeCells.C:97
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265