snappyRefineDriver.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2015 OpenFOAM Foundation
9  Copyright (C) 2015-2019 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "snappyRefineDriver.H"
30 #include "meshRefinement.H"
31 #include "fvMesh.H"
32 #include "Time.H"
33 #include "cellSet.H"
34 #include "syncTools.H"
35 #include "refinementParameters.H"
36 #include "refinementSurfaces.H"
37 #include "refinementFeatures.H"
38 #include "shellSurfaces.H"
39 #include "mapDistributePolyMesh.H"
40 #include "unitConversion.H"
41 #include "snapParameters.H"
42 #include "localPointRegion.H"
43 #include "IOmanip.H"
44 #include "labelVector.H"
45 #include "profiling.H"
46 #include "searchableSurfaces.H"
47 #include "fvMeshSubset.H"
48 #include "interpolationTable.H"
49 #include "snappyVoxelMeshDriver.H"
50 
51 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
52 
53 namespace Foam
54 {
55  defineTypeNameAndDebug(snappyRefineDriver, 0);
56 } // End namespace Foam
57 
58 
59 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
60 
61 Foam::snappyRefineDriver::snappyRefineDriver
62 (
63  meshRefinement& meshRefiner,
64  decompositionMethod& decomposer,
65  fvMeshDistribute& distributor,
66  const labelUList& globalToMasterPatch,
67  const labelUList& globalToSlavePatch,
68  const writer<scalar>& setFormatter,
69  const bool dryRun
70 )
71 :
72  meshRefiner_(meshRefiner),
73  decomposer_(decomposer),
74  distributor_(distributor),
75  globalToMasterPatch_(globalToMasterPatch),
76  globalToSlavePatch_(globalToSlavePatch),
77  setFormatter_(setFormatter),
78  dryRun_(dryRun)
79 {}
80 
81 
82 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
83 
84 Foam::label Foam::snappyRefineDriver::featureEdgeRefine
85 (
86  const refinementParameters& refineParams,
87  const label maxIter,
88  const label minRefine
89 )
90 {
91  if (dryRun_)
92  {
93  return 0;
94  }
95 
96  if (refineParams.minRefineCells() == -1)
97  {
98  // Special setting to be able to restart shm on meshes with inconsistent
99  // cellLevel/pointLevel
100  return 0;
101  }
102 
103  addProfiling(edge, "snappyHexMesh::refine::edge");
104  const fvMesh& mesh = meshRefiner_.mesh();
105 
106  label iter = 0;
107 
108  if (meshRefiner_.features().size() && maxIter > 0)
109  {
110  for (; iter < maxIter; iter++)
111  {
112  Info<< nl
113  << "Feature refinement iteration " << iter << nl
114  << "------------------------------" << nl
115  << endl;
116 
117  labelList candidateCells
118  (
119  meshRefiner_.refineCandidates
120  (
121  refineParams.locationsInMesh(),
122  refineParams.curvature(),
123  refineParams.planarAngle(),
124 
125  true, // featureRefinement
126  false, // featureDistanceRefinement
127  false, // internalRefinement
128  false, // surfaceRefinement
129  false, // curvatureRefinement
130  false, // smallFeatureRefinement
131  false, // gapRefinement
132  false, // bigGapRefinement
133  false, // spreadGapSize
134  refineParams.maxGlobalCells(),
135  refineParams.maxLocalCells()
136  )
137  );
138  labelList cellsToRefine
139  (
140  meshRefiner_.meshCutter().consistentRefinement
141  (
142  candidateCells,
143  true
144  )
145  );
146  Info<< "Determined cells to refine in = "
147  << mesh.time().cpuTimeIncrement() << " s" << endl;
148 
149 
150 
151  label nCellsToRefine = cellsToRefine.size();
152  reduce(nCellsToRefine, sumOp<label>());
153 
154  Info<< "Selected for feature refinement : " << nCellsToRefine
155  << " cells (out of " << mesh.globalData().nTotalCells()
156  << ')' << endl;
157 
158  if (nCellsToRefine <= minRefine)
159  {
160  Info<< "Stopping refining since too few cells selected."
161  << nl << endl;
162  break;
163  }
164 
165 
166  if (debug > 0)
167  {
168  const_cast<Time&>(mesh.time())++;
169  }
170 
171 
172  if
173  (
175  (
176  (mesh.nCells() >= refineParams.maxLocalCells()),
177  orOp<bool>()
178  )
179  )
180  {
181  meshRefiner_.balanceAndRefine
182  (
183  "feature refinement iteration " + name(iter),
184  decomposer_,
185  distributor_,
186  cellsToRefine,
187  refineParams.maxLoadUnbalance()
188  );
189  }
190  else
191  {
192  meshRefiner_.refineAndBalance
193  (
194  "feature refinement iteration " + name(iter),
195  decomposer_,
196  distributor_,
197  cellsToRefine,
198  refineParams.maxLoadUnbalance()
199  );
200  }
201  }
202  }
203  return iter;
204 }
205 
206 
207 Foam::label Foam::snappyRefineDriver::smallFeatureRefine
208 (
209  const refinementParameters& refineParams,
210  const label maxIter
211 )
212 {
213  if (dryRun_)
214  {
215  return 0;
216  }
217 
218  if (refineParams.minRefineCells() == -1)
219  {
220  // Special setting to be able to restart shm on meshes with inconsistent
221  // cellLevel/pointLevel
222  return 0;
223  }
224 
225  addProfiling(feature, "snappyHexMesh::refine::smallFeature");
226  const fvMesh& mesh = meshRefiner_.mesh();
227 
228  label iter = 0;
229 
230  // See if any surface has an extendedGapLevel
231  labelList surfaceMaxLevel(meshRefiner_.surfaces().maxGapLevel());
232  labelList shellMaxLevel(meshRefiner_.shells().maxGapLevel());
233 
234  if (max(surfaceMaxLevel) == 0 && max(shellMaxLevel) == 0)
235  {
236  return iter;
237  }
238 
239  for (; iter < maxIter; iter++)
240  {
241  Info<< nl
242  << "Small surface feature refinement iteration " << iter << nl
243  << "--------------------------------------------" << nl
244  << endl;
245 
246 
247  // Determine cells to refine
248  // ~~~~~~~~~~~~~~~~~~~~~~~~~
249 
250  labelList candidateCells
251  (
252  meshRefiner_.refineCandidates
253  (
254  refineParams.locationsInMesh(),
255  refineParams.curvature(),
256  refineParams.planarAngle(),
257 
258  false, // featureRefinement
259  false, // featureDistanceRefinement
260  false, // internalRefinement
261  false, // surfaceRefinement
262  false, // curvatureRefinement
263  true, // smallFeatureRefinement
264  false, // gapRefinement
265  false, // bigGapRefinement
266  false, // spreadGapSize
267  refineParams.maxGlobalCells(),
268  refineParams.maxLocalCells()
269  )
270  );
271 
272  labelList cellsToRefine
273  (
274  meshRefiner_.meshCutter().consistentRefinement
275  (
276  candidateCells,
277  true
278  )
279  );
280  Info<< "Determined cells to refine in = "
281  << mesh.time().cpuTimeIncrement() << " s" << endl;
282 
283 
284  label nCellsToRefine = cellsToRefine.size();
285  reduce(nCellsToRefine, sumOp<label>());
286 
287  Info<< "Selected for refinement : " << nCellsToRefine
288  << " cells (out of " << mesh.globalData().nTotalCells()
289  << ')' << endl;
290 
291  // Stop when no cells to refine or have done minimum necessary
292  // iterations and not enough cells to refine.
293  if (nCellsToRefine == 0)
294  {
295  Info<< "Stopping refining since too few cells selected."
296  << nl << endl;
297  break;
298  }
299 
300 
301  if (debug)
302  {
303  const_cast<Time&>(mesh.time())++;
304  }
305 
306 
307  if
308  (
310  (
311  (mesh.nCells() >= refineParams.maxLocalCells()),
312  orOp<bool>()
313  )
314  )
315  {
316  meshRefiner_.balanceAndRefine
317  (
318  "small feature refinement iteration " + name(iter),
319  decomposer_,
320  distributor_,
321  cellsToRefine,
322  refineParams.maxLoadUnbalance()
323  );
324  }
325  else
326  {
327  meshRefiner_.refineAndBalance
328  (
329  "small feature refinement iteration " + name(iter),
330  decomposer_,
331  distributor_,
332  cellsToRefine,
333  refineParams.maxLoadUnbalance()
334  );
335  }
336  }
337  return iter;
338 }
339 
340 
341 Foam::label Foam::snappyRefineDriver::surfaceOnlyRefine
342 (
343  const refinementParameters& refineParams,
344  const label maxIter
345 )
346 {
347  if (dryRun_)
348  {
349  return 0;
350  }
351 
352  if (refineParams.minRefineCells() == -1)
353  {
354  // Special setting to be able to restart shm on meshes with inconsistent
355  // cellLevel/pointLevel
356  return 0;
357  }
358 
359  addProfiling(surface, "snappyHexMesh::refine::surface");
360  const fvMesh& mesh = meshRefiner_.mesh();
361 
362  // Determine the maximum refinement level over all surfaces. This
363  // determines the minimum number of surface refinement iterations.
364  label overallMaxLevel = max(meshRefiner_.surfaces().maxLevel());
365 
366  label iter;
367  for (iter = 0; iter < maxIter; iter++)
368  {
369  Info<< nl
370  << "Surface refinement iteration " << iter << nl
371  << "------------------------------" << nl
372  << endl;
373 
374 
375  // Determine cells to refine
376  // ~~~~~~~~~~~~~~~~~~~~~~~~~
377  // Only look at surface intersections (minLevel and surface curvature),
378  // do not do internal refinement (refinementShells)
379 
380  labelList candidateCells
381  (
382  meshRefiner_.refineCandidates
383  (
384  refineParams.locationsInMesh(),
385  refineParams.curvature(),
386  refineParams.planarAngle(),
387 
388  false, // featureRefinement
389  false, // featureDistanceRefinement
390  false, // internalRefinement
391  true, // surfaceRefinement
392  true, // curvatureRefinement
393  false, // smallFeatureRefinement
394  false, // gapRefinement
395  false, // bigGapRefinement
396  false, // spreadGapSize
397  refineParams.maxGlobalCells(),
398  refineParams.maxLocalCells()
399  )
400  );
401  labelList cellsToRefine
402  (
403  meshRefiner_.meshCutter().consistentRefinement
404  (
405  candidateCells,
406  true
407  )
408  );
409  Info<< "Determined cells to refine in = "
410  << mesh.time().cpuTimeIncrement() << " s" << endl;
411 
412 
413  label nCellsToRefine = cellsToRefine.size();
414  reduce(nCellsToRefine, sumOp<label>());
415 
416  Info<< "Selected for refinement : " << nCellsToRefine
417  << " cells (out of " << mesh.globalData().nTotalCells()
418  << ')' << endl;
419 
420  // Stop when no cells to refine or have done minimum necessary
421  // iterations and not enough cells to refine.
422  if
423  (
424  nCellsToRefine == 0
425  || (
426  iter >= overallMaxLevel
427  && nCellsToRefine <= refineParams.minRefineCells()
428  )
429  )
430  {
431  Info<< "Stopping refining since too few cells selected."
432  << nl << endl;
433  break;
434  }
435 
436 
437  if (debug)
438  {
439  const_cast<Time&>(mesh.time())++;
440  }
441 
442 
443  if
444  (
446  (
447  (mesh.nCells() >= refineParams.maxLocalCells()),
448  orOp<bool>()
449  )
450  )
451  {
452  meshRefiner_.balanceAndRefine
453  (
454  "surface refinement iteration " + name(iter),
455  decomposer_,
456  distributor_,
457  cellsToRefine,
458  refineParams.maxLoadUnbalance()
459  );
460  }
461  else
462  {
463  meshRefiner_.refineAndBalance
464  (
465  "surface refinement iteration " + name(iter),
466  decomposer_,
467  distributor_,
468  cellsToRefine,
469  refineParams.maxLoadUnbalance()
470  );
471  }
472  }
473  return iter;
474 }
475 
476 
477 Foam::label Foam::snappyRefineDriver::gapOnlyRefine
478 (
479  const refinementParameters& refineParams,
480  const label maxIter
481 )
482 {
483  if (dryRun_)
484  {
485  return 0;
486  }
487 
488  if (refineParams.minRefineCells() == -1)
489  {
490  // Special setting to be able to restart shm on meshes with inconsistent
491  // cellLevel/pointLevel
492  return 0;
493  }
494 
495  const fvMesh& mesh = meshRefiner_.mesh();
496 
497  // Determine the maximum refinement level over all surfaces. This
498  // determines the minimum number of surface refinement iterations.
499 
500  label maxIncrement = 0;
501  const labelList& maxLevel = meshRefiner_.surfaces().maxLevel();
502  const labelList& gapLevel = meshRefiner_.surfaces().gapLevel();
503 
504  forAll(maxLevel, i)
505  {
506  maxIncrement = max(maxIncrement, gapLevel[i]-maxLevel[i]);
507  }
508 
509  label iter = 0;
510 
511  if (maxIncrement == 0)
512  {
513  return iter;
514  }
515 
516  for (iter = 0; iter < maxIter; iter++)
517  {
518  Info<< nl
519  << "Gap refinement iteration " << iter << nl
520  << "--------------------------" << nl
521  << endl;
522 
523 
524  // Determine cells to refine
525  // ~~~~~~~~~~~~~~~~~~~~~~~~~
526  // Only look at surface intersections (minLevel and surface curvature),
527  // do not do internal refinement (refinementShells)
528 
529  labelList candidateCells
530  (
531  meshRefiner_.refineCandidates
532  (
533  refineParams.locationsInMesh(),
534  refineParams.curvature(),
535  refineParams.planarAngle(),
536 
537  false, // featureRefinement
538  false, // featureDistanceRefinement
539  false, // internalRefinement
540  false, // surfaceRefinement
541  false, // curvatureRefinement
542  false, // smallFeatureRefinement
543  true, // gapRefinement
544  false, // bigGapRefinement
545  false, // spreadGapSize
546  refineParams.maxGlobalCells(),
547  refineParams.maxLocalCells()
548  )
549  );
550 
552  {
553  Pout<< "Writing current mesh to time "
554  << meshRefiner_.timeName() << endl;
555  meshRefiner_.write
556  (
559  (
562  ),
563  mesh.time().path()/meshRefiner_.timeName()
564  );
565  Pout<< "Dumped mesh in = "
566  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
567 
568 
569  Pout<< "Dumping " << candidateCells.size()
570  << " cells to cellSet candidateCellsFromGap." << endl;
571  cellSet c(mesh, "candidateCellsFromGap", candidateCells);
572  c.instance() = meshRefiner_.timeName();
573  c.write();
574  }
575 
576  // Grow by one layer to make sure we're covering the gap
577  {
578  boolList isCandidateCell(mesh.nCells(), false);
579  forAll(candidateCells, i)
580  {
581  isCandidateCell[candidateCells[i]] = true;
582  }
583 
584  for (label i=0; i<1; i++)
585  {
586  boolList newIsCandidateCell(isCandidateCell);
587 
588  // Internal faces
589  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
590  {
591  label own = mesh.faceOwner()[facei];
592  label nei = mesh.faceNeighbour()[facei];
593 
594  if (isCandidateCell[own] != isCandidateCell[nei])
595  {
596  newIsCandidateCell[own] = true;
597  newIsCandidateCell[nei] = true;
598  }
599  }
600 
601  // Get coupled boundary condition values
602  boolList neiIsCandidateCell;
604  (
605  mesh,
606  isCandidateCell,
607  neiIsCandidateCell
608  );
609 
610  // Boundary faces
611  for
612  (
613  label facei = mesh.nInternalFaces();
614  facei < mesh.nFaces();
615  facei++
616  )
617  {
618  label own = mesh.faceOwner()[facei];
619  label bFacei = facei-mesh.nInternalFaces();
620 
621  if (isCandidateCell[own] != neiIsCandidateCell[bFacei])
622  {
623  newIsCandidateCell[own] = true;
624  }
625  }
626 
627  isCandidateCell.transfer(newIsCandidateCell);
628  }
629 
630  label n = 0;
631  forAll(isCandidateCell, celli)
632  {
633  if (isCandidateCell[celli])
634  {
635  n++;
636  }
637  }
638  candidateCells.setSize(n);
639  n = 0;
640  forAll(isCandidateCell, celli)
641  {
642  if (isCandidateCell[celli])
643  {
644  candidateCells[n++] = celli;
645  }
646  }
647  }
648 
649 
651  {
652  Pout<< "Dumping " << candidateCells.size()
653  << " cells to cellSet candidateCellsFromGapPlusBuffer." << endl;
654  cellSet c(mesh, "candidateCellsFromGapPlusBuffer", candidateCells);
655  c.instance() = meshRefiner_.timeName();
656  c.write();
657  }
658 
659 
660  labelList cellsToRefine
661  (
662  meshRefiner_.meshCutter().consistentRefinement
663  (
664  candidateCells,
665  true
666  )
667  );
668  Info<< "Determined cells to refine in = "
669  << mesh.time().cpuTimeIncrement() << " s" << endl;
670 
671 
672  label nCellsToRefine = cellsToRefine.size();
673  reduce(nCellsToRefine, sumOp<label>());
674 
675  Info<< "Selected for refinement : " << nCellsToRefine
676  << " cells (out of " << mesh.globalData().nTotalCells()
677  << ')' << endl;
678 
679  // Stop when no cells to refine or have done minimum necessary
680  // iterations and not enough cells to refine.
681  if
682  (
683  nCellsToRefine == 0
684  || (
685  iter >= maxIncrement
686  && nCellsToRefine <= refineParams.minRefineCells()
687  )
688  )
689  {
690  Info<< "Stopping refining since too few cells selected."
691  << nl << endl;
692  break;
693  }
694 
695 
696  if (debug)
697  {
698  const_cast<Time&>(mesh.time())++;
699  }
700 
701 
702  if
703  (
705  (
706  (mesh.nCells() >= refineParams.maxLocalCells()),
707  orOp<bool>()
708  )
709  )
710  {
711  meshRefiner_.balanceAndRefine
712  (
713  "gap refinement iteration " + name(iter),
714  decomposer_,
715  distributor_,
716  cellsToRefine,
717  refineParams.maxLoadUnbalance()
718  );
719  }
720  else
721  {
722  meshRefiner_.refineAndBalance
723  (
724  "gap refinement iteration " + name(iter),
725  decomposer_,
726  distributor_,
727  cellsToRefine,
728  refineParams.maxLoadUnbalance()
729  );
730  }
731  }
732  return iter;
733 }
734 
735 
736 Foam::label Foam::snappyRefineDriver::surfaceProximityBlock
737 (
738  const refinementParameters& refineParams,
739  const label maxIter
740 )
741 {
742  if (refineParams.minRefineCells() == -1)
743  {
744  // Special setting to be able to restart shm on meshes with inconsistent
745  // cellLevel/pointLevel
746  return 0;
747  }
748 
749  fvMesh& mesh = meshRefiner_.mesh();
750 
751  if (min(meshRefiner_.surfaces().blockLevel()) == labelMax)
752  {
753  return 0;
754  }
755 
756  label iter = 0;
757 
758  for (iter = 0; iter < maxIter; iter++)
759  {
760  Info<< nl
761  << "Gap blocking iteration " << iter << nl
762  << "------------------------" << nl
763  << endl;
764 
765 
766  // Determine cells to block
767  // ~~~~~~~~~~~~~~~~~~~~~~~~
768 
769  meshRefiner_.removeGapCells
770  (
771  refineParams.planarAngle(),
772  meshRefiner_.surfaces().blockLevel(),
773  globalToMasterPatch_,
774  refineParams.nFilterIter()
775  );
776 
777  if (debug)
778  {
779  const_cast<Time&>(mesh.time())++;
780  Pout<< "Writing gap blocking iteration "
781  << iter << " mesh to time " << meshRefiner_.timeName()
782  << endl;
783  meshRefiner_.write
784  (
787  (
790  ),
791  mesh.time().path()/meshRefiner_.timeName()
792  );
793  }
794  }
795  return iter;
796 }
797 
798 
799 Foam::label Foam::snappyRefineDriver::bigGapOnlyRefine
800 (
801  const refinementParameters& refineParams,
802  const bool spreadGapSize,
803  const label maxIter
804 )
805 {
806  if (refineParams.minRefineCells() == -1)
807  {
808  // Special setting to be able to restart shm on meshes with inconsistent
809  // cellLevel/pointLevel
810  return 0;
811  }
812 
813  if (dryRun_)
814  {
815  return 0;
816  }
817 
818  const fvMesh& mesh = meshRefiner_.mesh();
819 
820  label iter = 0;
821 
822  // See if any surface has an extendedGapLevel
823  labelList surfaceMaxLevel(meshRefiner_.surfaces().maxGapLevel());
824  labelList shellMaxLevel(meshRefiner_.shells().maxGapLevel());
825 
826  label overallMaxLevel(max(max(surfaceMaxLevel), max(shellMaxLevel)));
827 
828  if (overallMaxLevel == 0)
829  {
830  return iter;
831  }
832 
833 
834  for (; iter < maxIter; iter++)
835  {
836  Info<< nl
837  << "Big gap refinement iteration " << iter << nl
838  << "------------------------------" << nl
839  << endl;
840 
841 
842  // Determine cells to refine
843  // ~~~~~~~~~~~~~~~~~~~~~~~~~
844 
845  labelList candidateCells
846  (
847  meshRefiner_.refineCandidates
848  (
849  refineParams.locationsInMesh(),
850  refineParams.curvature(),
851  refineParams.planarAngle(),
852 
853  false, // featureRefinement
854  false, // featureDistanceRefinement
855  false, // internalRefinement
856  false, // surfaceRefinement
857  false, // curvatureRefinement
858  false, // smallFeatureRefinement
859  false, // gapRefinement
860  true, // bigGapRefinement
861  spreadGapSize, // spreadGapSize
862  refineParams.maxGlobalCells(),
863  refineParams.maxLocalCells()
864  )
865  );
866 
867 
869  {
870  Pout<< "Writing current mesh to time "
871  << meshRefiner_.timeName() << endl;
872  meshRefiner_.write
873  (
876  (
879  ),
880  mesh.time().path()/meshRefiner_.timeName()
881  );
882  Pout<< "Dumped mesh in = "
883  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
884 
885  Pout<< "Dumping " << candidateCells.size()
886  << " cells to cellSet candidateCellsFromBigGap." << endl;
887  cellSet c(mesh, "candidateCellsFromBigGap", candidateCells);
888  c.instance() = meshRefiner_.timeName();
889  c.write();
890  }
891 
892  labelList cellsToRefine
893  (
894  meshRefiner_.meshCutter().consistentRefinement
895  (
896  candidateCells,
897  true
898  )
899  );
900  Info<< "Determined cells to refine in = "
901  << mesh.time().cpuTimeIncrement() << " s" << endl;
902 
903 
904  label nCellsToRefine = cellsToRefine.size();
905  reduce(nCellsToRefine, sumOp<label>());
906 
907  Info<< "Selected for refinement : " << nCellsToRefine
908  << " cells (out of " << mesh.globalData().nTotalCells()
909  << ')' << endl;
910 
911  // Stop when no cells to refine or have done minimum necessary
912  // iterations and not enough cells to refine.
913  if
914  (
915  nCellsToRefine == 0
916  || (
917  iter >= overallMaxLevel
918  && nCellsToRefine <= refineParams.minRefineCells()
919  )
920  )
921  {
922  Info<< "Stopping refining since too few cells selected."
923  << nl << endl;
924  break;
925  }
926 
927 
928  if (debug)
929  {
930  const_cast<Time&>(mesh.time())++;
931  }
932 
933 
934  if
935  (
937  (
938  (mesh.nCells() >= refineParams.maxLocalCells()),
939  orOp<bool>()
940  )
941  )
942  {
943  meshRefiner_.balanceAndRefine
944  (
945  "big gap refinement iteration " + name(iter),
946  decomposer_,
947  distributor_,
948  cellsToRefine,
949  refineParams.maxLoadUnbalance()
950  );
951  }
952  else
953  {
954  meshRefiner_.refineAndBalance
955  (
956  "big gap refinement iteration " + name(iter),
957  decomposer_,
958  distributor_,
959  cellsToRefine,
960  refineParams.maxLoadUnbalance()
961  );
962  }
963  }
964  return iter;
965 }
966 
967 
968 Foam::label Foam::snappyRefineDriver::danglingCellRefine
969 (
970  const refinementParameters& refineParams,
971  const label nFaces,
972  const label maxIter
973 )
974 {
975  if (refineParams.minRefineCells() == -1)
976  {
977  // Special setting to be able to restart shm on meshes with inconsistent
978  // cellLevel/pointLevel
979  return 0;
980  }
981 
982  if (dryRun_)
983  {
984  return 0;
985  }
986 
987  addProfiling(dangling, "snappyHexMesh::refine::danglingCell");
988  const fvMesh& mesh = meshRefiner_.mesh();
989 
990  label iter;
991  for (iter = 0; iter < maxIter; iter++)
992  {
993  Info<< nl
994  << "Dangling coarse cells refinement iteration " << iter << nl
995  << "--------------------------------------------" << nl
996  << endl;
997 
998 
999  // Determine cells to refine
1000  // ~~~~~~~~~~~~~~~~~~~~~~~~~
1001 
1002  const cellList& cells = mesh.cells();
1003  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
1004 
1005  labelList candidateCells;
1006  {
1007  cellSet candidateCellSet(mesh, "candidateCells", cells.size()/1000);
1008 
1009  forAll(cells, celli)
1010  {
1011  const cell& cFaces = cells[celli];
1012 
1013  label nIntFaces = 0;
1014  forAll(cFaces, i)
1015  {
1016  label bFacei = cFaces[i]-mesh.nInternalFaces();
1017  if (bFacei < 0)
1018  {
1019  nIntFaces++;
1020  }
1021  else
1022  {
1023  label patchi = pbm.patchID()[bFacei];
1024  if (pbm[patchi].coupled())
1025  {
1026  nIntFaces++;
1027  }
1028  }
1029  }
1030 
1031  if (nIntFaces == nFaces)
1032  {
1033  candidateCellSet.insert(celli);
1034  }
1035  }
1036 
1038  {
1039  Pout<< "Dumping " << candidateCellSet.size()
1040  << " cells to cellSet candidateCellSet." << endl;
1041  candidateCellSet.instance() = meshRefiner_.timeName();
1042  candidateCellSet.write();
1043  }
1044  candidateCells = candidateCellSet.toc();
1045  }
1046 
1047 
1048 
1049  labelList cellsToRefine
1050  (
1051  meshRefiner_.meshCutter().consistentRefinement
1052  (
1053  candidateCells,
1054  true
1055  )
1056  );
1057  Info<< "Determined cells to refine in = "
1058  << mesh.time().cpuTimeIncrement() << " s" << endl;
1059 
1060 
1061  label nCellsToRefine = cellsToRefine.size();
1062  reduce(nCellsToRefine, sumOp<label>());
1063 
1064  Info<< "Selected for refinement : " << nCellsToRefine
1065  << " cells (out of " << mesh.globalData().nTotalCells()
1066  << ')' << endl;
1067 
1068  // Stop when no cells to refine. After a few iterations check if too
1069  // few cells
1070  if
1071  (
1072  nCellsToRefine == 0
1073  || (
1074  iter >= 1
1075  && nCellsToRefine <= refineParams.minRefineCells()
1076  )
1077  )
1078  {
1079  Info<< "Stopping refining since too few cells selected."
1080  << nl << endl;
1081  break;
1082  }
1083 
1084 
1085  if (debug)
1086  {
1087  const_cast<Time&>(mesh.time())++;
1088  }
1089 
1090 
1091  if
1092  (
1093  returnReduce
1094  (
1095  (mesh.nCells() >= refineParams.maxLocalCells()),
1096  orOp<bool>()
1097  )
1098  )
1099  {
1100  meshRefiner_.balanceAndRefine
1101  (
1102  "coarse cell refinement iteration " + name(iter),
1103  decomposer_,
1104  distributor_,
1105  cellsToRefine,
1106  refineParams.maxLoadUnbalance()
1107  );
1108  }
1109  else
1110  {
1111  meshRefiner_.refineAndBalance
1112  (
1113  "coarse cell refinement iteration " + name(iter),
1114  decomposer_,
1115  distributor_,
1116  cellsToRefine,
1117  refineParams.maxLoadUnbalance()
1118  );
1119  }
1120  }
1121  return iter;
1122 }
1123 
1124 
1125 // Detect cells with opposing intersected faces of differing refinement
1126 // level and refine them.
1127 Foam::label Foam::snappyRefineDriver::refinementInterfaceRefine
1128 (
1129  const refinementParameters& refineParams,
1130  const label maxIter
1131 )
1132 {
1133  if (refineParams.minRefineCells() == -1)
1134  {
1135  // Special setting to be able to restart shm on meshes with inconsistent
1136  // cellLevel/pointLevel
1137  return 0;
1138  }
1139 
1140  if (dryRun_)
1141  {
1142  return 0;
1143  }
1144 
1145  addProfiling(interface, "snappyHexMesh::refine::transition");
1146  const fvMesh& mesh = meshRefiner_.mesh();
1147 
1148  label iter = 0;
1149 
1150  if (refineParams.interfaceRefine())
1151  {
1152  for (;iter < maxIter; iter++)
1153  {
1154  Info<< nl
1155  << "Refinement transition refinement iteration " << iter << nl
1156  << "--------------------------------------------" << nl
1157  << endl;
1158 
1159  const labelList& surfaceIndex = meshRefiner_.surfaceIndex();
1160  const hexRef8& cutter = meshRefiner_.meshCutter();
1161  const vectorField& fA = mesh.faceAreas();
1162  const labelList& faceOwner = mesh.faceOwner();
1163 
1164 
1165  // Determine cells to refine
1166  // ~~~~~~~~~~~~~~~~~~~~~~~~~
1167 
1168  const cellList& cells = mesh.cells();
1169 
1170  labelList candidateCells;
1171  {
1172  // Pass1: pick up cells with differing face level
1173 
1174  cellSet transitionCells
1175  (
1176  mesh,
1177  "transitionCells",
1178  cells.size()/100
1179  );
1180 
1181  forAll(cells, celli)
1182  {
1183  const cell& cFaces = cells[celli];
1184  label cLevel = cutter.cellLevel()[celli];
1185 
1186  forAll(cFaces, cFacei)
1187  {
1188  label facei = cFaces[cFacei];
1189 
1190  if (surfaceIndex[facei] != -1)
1191  {
1192  label fLevel = cutter.faceLevel(facei);
1193  if (fLevel != cLevel)
1194  {
1195  transitionCells.insert(celli);
1196  }
1197  }
1198  }
1199  }
1200 
1201 
1202  cellSet candidateCellSet
1203  (
1204  mesh,
1205  "candidateCells",
1206  cells.size()/1000
1207  );
1208 
1209  // Pass2: check for oppositeness
1210 
1211  //for (const label celli : transitionCells)
1212  //{
1213  // const cell& cFaces = cells[celli];
1214  // const point& cc = cellCentres[celli];
1215  // const scalar rCVol = pow(cellVolumes[celli], -5.0/3.0);
1216  //
1217  // // Determine principal axes of cell
1218  // symmTensor R(Zero);
1219  //
1220  // forAll(cFaces, i)
1221  // {
1222  // label facei = cFaces[i];
1223  //
1224  // const point& fc = faceCentres[facei];
1225  //
1226  // // Calculate face-pyramid volume
1227  // scalar pyrVol = 1.0/3.0 * fA[facei] & (fc-cc);
1228  //
1229  // if (faceOwner[facei] != celli)
1230  // {
1231  // pyrVol = -pyrVol;
1232  // }
1233  //
1234  // // Calculate face-pyramid centre
1235  // vector pc = (3.0/4.0)*fc + (1.0/4.0)*cc;
1236  //
1237  // R += pyrVol*sqr(pc-cc)*rCVol;
1238  // }
1239  //
1240  // //- MEJ: Problem: truncation errors cause complex evs
1241  // vector lambdas(eigenValues(R));
1242  // const tensor axes(eigenVectors(R, lambdas));
1243  //
1244  //
1245  // // Check if this cell has
1246  // // - opposing sides intersected
1247  // // - which are of different refinement level
1248  // // - plus the inbetween face
1249  //
1250  // labelVector plusFaceLevel(labelVector(-1, -1, -1));
1251  // labelVector minFaceLevel(labelVector(-1, -1, -1));
1252  //
1253  // forAll(cFaces, cFacei)
1254  // {
1255  // label facei = cFaces[cFacei];
1256  //
1257  // if (surfaceIndex[facei] != -1)
1258  // {
1259  // label fLevel = cutter.faceLevel(facei);
1260  //
1261  // // Get outwards pointing normal
1262  // vector n = fA[facei]/mag(fA[facei]);
1263  // if (faceOwner[facei] != celli)
1264  // {
1265  // n = -n;
1266  // }
1267  //
1268  // // What is major direction and sign
1269  // direction cmpt = vector::X;
1270  // scalar maxComp = (n&axes.x());
1271  //
1272  // scalar yComp = (n&axes.y());
1273  // scalar zComp = (n&axes.z());
1274  //
1275  // if (mag(yComp) > mag(maxComp))
1276  // {
1277  // maxComp = yComp;
1278  // cmpt = vector::Y;
1279  // }
1280  //
1281  // if (mag(zComp) > mag(maxComp))
1282  // {
1283  // maxComp = zComp;
1284  // cmpt = vector::Z;
1285  // }
1286  //
1287  // if (maxComp > 0)
1288  // {
1289  // plusFaceLevel[cmpt] = max
1290  // (
1291  // plusFaceLevel[cmpt],
1292  // fLevel
1293  // );
1294  // }
1295  // else
1296  // {
1297  // minFaceLevel[cmpt] = max
1298  // (
1299  // minFaceLevel[cmpt],
1300  // fLevel
1301  // );
1302  // }
1303  // }
1304  // }
1305  //
1306  // // Check if we picked up any opposite differing level
1307  // for (direction dir = 0; dir < vector::nComponents; dir++)
1308  // {
1309  // if
1310  // (
1311  // plusFaceLevel[dir] != -1
1312  // && minFaceLevel[dir] != -1
1313  // && plusFaceLevel[dir] != minFaceLevel[dir]
1314  // )
1315  // {
1316  // candidateCellSet.insert(celli);
1317  // }
1318  // }
1319  //}
1320 
1321  const scalar oppositeCos = Foam::cos(degToRad(135.0));
1322 
1323  for (const label celli : transitionCells)
1324  {
1325  const cell& cFaces = cells[celli];
1326  label cLevel = cutter.cellLevel()[celli];
1327 
1328  // Detect opposite intersection
1329  bool foundOpposite = false;
1330 
1331  forAll(cFaces, cFacei)
1332  {
1333  label facei = cFaces[cFacei];
1334 
1335  if
1336  (
1337  surfaceIndex[facei] != -1
1338  && cutter.faceLevel(facei) > cLevel
1339  )
1340  {
1341  // Get outwards pointing normal
1342  vector n = fA[facei]/mag(fA[facei]);
1343  if (faceOwner[facei] != celli)
1344  {
1345  n = -n;
1346  }
1347 
1348  // Check for any opposite intersection
1349  forAll(cFaces, cFaceI2)
1350  {
1351  label face2i = cFaces[cFaceI2];
1352 
1353  if
1354  (
1355  face2i != facei
1356  && surfaceIndex[face2i] != -1
1357  )
1358  {
1359  // Get outwards pointing normal
1360  vector n2 = fA[face2i]/mag(fA[face2i]);
1361  if (faceOwner[face2i] != celli)
1362  {
1363  n2 = -n2;
1364  }
1365 
1366 
1367  if ((n&n2) < oppositeCos)
1368  {
1369  foundOpposite = true;
1370  break;
1371  }
1372  }
1373  }
1374 
1375  if (foundOpposite)
1376  {
1377  break;
1378  }
1379  }
1380  }
1381 
1382 
1383  if (foundOpposite)
1384  {
1385  candidateCellSet.insert(celli);
1386  }
1387  }
1388 
1390  {
1391  Pout<< "Dumping " << candidateCellSet.size()
1392  << " cells to cellSet candidateCellSet." << endl;
1393  candidateCellSet.instance() = meshRefiner_.timeName();
1394  candidateCellSet.write();
1395  }
1396  candidateCells = candidateCellSet.toc();
1397  }
1398 
1399 
1400 
1401  labelList cellsToRefine
1402  (
1403  meshRefiner_.meshCutter().consistentRefinement
1404  (
1405  candidateCells,
1406  true
1407  )
1408  );
1409  Info<< "Determined cells to refine in = "
1410  << mesh.time().cpuTimeIncrement() << " s" << endl;
1411 
1412 
1413  label nCellsToRefine = cellsToRefine.size();
1414  reduce(nCellsToRefine, sumOp<label>());
1415 
1416  Info<< "Selected for refinement : " << nCellsToRefine
1417  << " cells (out of " << mesh.globalData().nTotalCells()
1418  << ')' << endl;
1419 
1420  // Stop when no cells to refine. After a few iterations check if too
1421  // few cells
1422  if
1423  (
1424  nCellsToRefine == 0
1425  || (
1426  iter >= 1
1427  && nCellsToRefine <= refineParams.minRefineCells()
1428  )
1429  )
1430  {
1431  Info<< "Stopping refining since too few cells selected."
1432  << nl << endl;
1433  break;
1434  }
1435 
1436 
1437  if (debug)
1438  {
1439  const_cast<Time&>(mesh.time())++;
1440  }
1441 
1442 
1443  if
1444  (
1445  returnReduce
1446  (
1447  (mesh.nCells() >= refineParams.maxLocalCells()),
1448  orOp<bool>()
1449  )
1450  )
1451  {
1452  meshRefiner_.balanceAndRefine
1453  (
1454  "interface cell refinement iteration " + name(iter),
1455  decomposer_,
1456  distributor_,
1457  cellsToRefine,
1458  refineParams.maxLoadUnbalance()
1459  );
1460  }
1461  else
1462  {
1463  meshRefiner_.refineAndBalance
1464  (
1465  "interface cell refinement iteration " + name(iter),
1466  decomposer_,
1467  distributor_,
1468  cellsToRefine,
1469  refineParams.maxLoadUnbalance()
1470  );
1471  }
1472  }
1473  }
1474  return iter;
1475 }
1476 
1477 
1478 void Foam::snappyRefineDriver::removeInsideCells
1479 (
1480  const refinementParameters& refineParams,
1481  const label nBufferLayers
1482 )
1483 {
1484  // Skip if no limitRegion and zero bufferLayers
1485  if (meshRefiner_.limitShells().shells().size() == 0 && nBufferLayers == 0)
1486  {
1487  return;
1488  }
1489 
1490  if (dryRun_)
1491  {
1492  return;
1493  }
1494 
1495  Info<< nl
1496  << "Removing mesh beyond surface intersections" << nl
1497  << "------------------------------------------" << nl
1498  << endl;
1499 
1500  const fvMesh& mesh = meshRefiner_.mesh();
1501 
1502  if (debug)
1503  {
1504  const_cast<Time&>(mesh.time())++;
1505  }
1506 
1507  // Remove any cells inside limitShells with level -1
1508  meshRefiner_.removeLimitShells
1509  (
1510  nBufferLayers,
1511  1,
1512  globalToMasterPatch_,
1513  globalToSlavePatch_,
1514  refineParams.locationsInMesh(),
1515  refineParams.zonesInMesh()
1516  );
1517 
1518  // Fix any additional (e.g. locationsOutsideMesh). Note: probably not
1519  // necessary.
1520  meshRefiner_.splitMesh
1521  (
1522  nBufferLayers, // nBufferLayers
1523  refineParams.nErodeCellZone(),
1524  globalToMasterPatch_,
1525  globalToSlavePatch_,
1526  refineParams.locationsInMesh(),
1527  refineParams.zonesInMesh(),
1528  refineParams.locationsOutsideMesh(),
1529  setFormatter_
1530  );
1531 
1533  {
1534  const_cast<Time&>(mesh.time())++;
1535 
1536  Pout<< "Writing subsetted mesh to time "
1537  << meshRefiner_.timeName() << endl;
1538  meshRefiner_.write
1539  (
1542  (
1545  ),
1546  mesh.time().path()/meshRefiner_.timeName()
1547  );
1548  Pout<< "Dumped mesh in = "
1549  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
1550  }
1551 }
1552 
1553 
1554 Foam::label Foam::snappyRefineDriver::shellRefine
1555 (
1556  const refinementParameters& refineParams,
1557  const label maxIter
1558 )
1559 {
1560  if (dryRun_)
1561  {
1562  return 0;
1563  }
1564 
1565  if (refineParams.minRefineCells() == -1)
1566  {
1567  // Special setting to be able to restart shm on meshes with inconsistent
1568  // cellLevel/pointLevel
1569  return 0;
1570  }
1571 
1572  addProfiling(shell, "snappyHexMesh::refine::shell");
1573  const fvMesh& mesh = meshRefiner_.mesh();
1574 
1575  // Mark current boundary faces with 0. Have meshRefiner maintain them.
1576  meshRefiner_.userFaceData().setSize(1);
1577 
1578  // mark list to remove any refined faces
1579  meshRefiner_.userFaceData()[0].first() = meshRefinement::REMOVE;
1580  meshRefiner_.userFaceData()[0].second() = ListOps::createWithValue<label>
1581  (
1582  mesh.nFaces(),
1583  meshRefiner_.intersectedFaces(),
1584  0, // set value
1585  -1 // default value
1586  );
1587 
1588  // Determine the maximum refinement level over all volume refinement
1589  // regions. This determines the minimum number of shell refinement
1590  // iterations.
1591  label overallMaxShellLevel = meshRefiner_.shells().maxLevel();
1592 
1593  label iter;
1594  for (iter = 0; iter < maxIter; iter++)
1595  {
1596  Info<< nl
1597  << "Shell refinement iteration " << iter << nl
1598  << "----------------------------" << nl
1599  << endl;
1600 
1601  labelList candidateCells
1602  (
1603  meshRefiner_.refineCandidates
1604  (
1605  refineParams.locationsInMesh(),
1606  refineParams.curvature(),
1607  refineParams.planarAngle(),
1608 
1609  false, // featureRefinement
1610  true, // featureDistanceRefinement
1611  true, // internalRefinement
1612  false, // surfaceRefinement
1613  false, // curvatureRefinement
1614  false, // smallFeatureRefinement
1615  false, // gapRefinement
1616  false, // bigGapRefinement
1617  false, // spreadGapSize
1618  refineParams.maxGlobalCells(),
1619  refineParams.maxLocalCells()
1620  )
1621  );
1622 
1624  {
1625  Pout<< "Dumping " << candidateCells.size()
1626  << " cells to cellSet candidateCellsFromShells." << endl;
1627 
1628  cellSet c(mesh, "candidateCellsFromShells", candidateCells);
1629  c.instance() = meshRefiner_.timeName();
1630  c.write();
1631  }
1632 
1633  // Problem choosing starting faces for bufferlayers (bFaces)
1634  // - we can't use the current intersected boundary faces
1635  // (intersectedFaces) since this grows indefinitely
1636  // - if we use 0 faces we don't satisfy bufferLayers from the
1637  // surface.
1638  // - possibly we want to have bFaces only the initial set of faces
1639  // and maintain the list while doing the refinement.
1640  labelList bFaces
1641  (
1642  findIndices(meshRefiner_.userFaceData()[0].second(), 0)
1643  );
1644 
1645  //Info<< "Collected boundary faces : "
1646  // << returnReduce(bFaces.size(), sumOp<label>()) << endl;
1647 
1648  labelList cellsToRefine;
1649 
1650  if (refineParams.nBufferLayers() <= 2)
1651  {
1652  cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement
1653  (
1654  refineParams.nBufferLayers(),
1655  candidateCells, // cells to refine
1656  bFaces, // faces for nBufferLayers
1657  1, // point difference
1658  meshRefiner_.intersectedPoints() // points to check
1659  );
1660  }
1661  else
1662  {
1663  cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement2
1664  (
1665  refineParams.nBufferLayers(),
1666  candidateCells, // cells to refine
1667  bFaces // faces for nBufferLayers
1668  );
1669  }
1670 
1671  Info<< "Determined cells to refine in = "
1672  << mesh.time().cpuTimeIncrement() << " s" << endl;
1673 
1674 
1675  label nCellsToRefine = cellsToRefine.size();
1676  reduce(nCellsToRefine, sumOp<label>());
1677 
1678  Info<< "Selected for internal refinement : " << nCellsToRefine
1679  << " cells (out of " << mesh.globalData().nTotalCells()
1680  << ')' << endl;
1681 
1682  // Stop when no cells to refine or have done minimum necessary
1683  // iterations and not enough cells to refine.
1684  if
1685  (
1686  nCellsToRefine == 0
1687  || (
1688  iter >= overallMaxShellLevel
1689  && nCellsToRefine <= refineParams.minRefineCells()
1690  )
1691  )
1692  {
1693  Info<< "Stopping refining since too few cells selected."
1694  << nl << endl;
1695  break;
1696  }
1697 
1698 
1699  if (debug)
1700  {
1701  const_cast<Time&>(mesh.time())++;
1702  }
1703 
1704  if
1705  (
1706  returnReduce
1707  (
1708  (mesh.nCells() >= refineParams.maxLocalCells()),
1709  orOp<bool>()
1710  )
1711  )
1712  {
1713  meshRefiner_.balanceAndRefine
1714  (
1715  "shell refinement iteration " + name(iter),
1716  decomposer_,
1717  distributor_,
1718  cellsToRefine,
1719  refineParams.maxLoadUnbalance()
1720  );
1721  }
1722  else
1723  {
1724  meshRefiner_.refineAndBalance
1725  (
1726  "shell refinement iteration " + name(iter),
1727  decomposer_,
1728  distributor_,
1729  cellsToRefine,
1730  refineParams.maxLoadUnbalance()
1731  );
1732  }
1733  }
1734  meshRefiner_.userFaceData().clear();
1735 
1736  return iter;
1737 }
1738 
1739 
1740 Foam::label Foam::snappyRefineDriver::directionalShellRefine
1741 (
1742  const refinementParameters& refineParams,
1743  const label maxIter
1744 )
1745 {
1746  if (dryRun_)
1747  {
1748  return 0;
1749  }
1750 
1751  addProfiling(shell, "snappyHexMesh::refine::directionalShell");
1752  const fvMesh& mesh = meshRefiner_.mesh();
1753  const shellSurfaces& shells = meshRefiner_.shells();
1754 
1755  labelList& cellLevel =
1756  const_cast<labelIOList&>(meshRefiner_.meshCutter().cellLevel());
1757  labelList& pointLevel =
1758  const_cast<labelIOList&>(meshRefiner_.meshCutter().pointLevel());
1759 
1760 
1761  // Determine the minimum and maximum cell levels that are candidates for
1762  // directional refinement
1763  const labelPairList dirSelect(shells.directionalSelectLevel());
1764  label overallMinLevel = labelMax;
1765  label overallMaxLevel = labelMin;
1766  forAll(dirSelect, shelli)
1767  {
1768  overallMinLevel = min(dirSelect[shelli].first(), overallMinLevel);
1769  overallMaxLevel = max(dirSelect[shelli].second(), overallMaxLevel);
1770  }
1771 
1772  if (overallMinLevel > overallMaxLevel)
1773  {
1774  return 0;
1775  }
1776 
1777  // Maintain directional refinement levels
1778  List<labelVector> dirCellLevel(cellLevel.size());
1779  forAll(cellLevel, celli)
1780  {
1781  dirCellLevel[celli] = labelVector::uniform(cellLevel[celli]);
1782  }
1783 
1784  label iter;
1785  for (iter = 0; iter < maxIter; iter++)
1786  {
1787  Info<< nl
1788  << "Directional shell refinement iteration " << iter << nl
1789  << "----------------------------------------" << nl
1790  << endl;
1791 
1792  label nAllRefine = 0;
1793 
1794  for (direction dir = 0; dir < vector::nComponents; dir++)
1795  {
1796  // Select the cells that need to be refined in certain direction:
1797  // - cell inside/outside shell
1798  // - original cellLevel (using mapping) mentioned in levelIncrement
1799  // - dirCellLevel not yet up to cellLevel+levelIncrement
1800 
1801 
1802  // Extract component of directional level
1803  labelList currentLevel(dirCellLevel.size());
1804  forAll(dirCellLevel, celli)
1805  {
1806  currentLevel[celli] = dirCellLevel[celli][dir];
1807  }
1808 
1809  labelList candidateCells
1810  (
1811  meshRefiner_.directionalRefineCandidates
1812  (
1813  refineParams.maxGlobalCells(),
1814  refineParams.maxLocalCells(),
1815  currentLevel,
1816  dir
1817  )
1818  );
1819 
1820  // Extend to keep 2:1 ratio
1821  labelList cellsToRefine
1822  (
1823  meshRefiner_.meshCutter().consistentRefinement
1824  (
1825  currentLevel,
1826  candidateCells,
1827  true
1828  )
1829  );
1830 
1831  Info<< "Determined cells to refine in = "
1832  << mesh.time().cpuTimeIncrement() << " s" << endl;
1833 
1834  label nCellsToRefine = cellsToRefine.size();
1835  reduce(nCellsToRefine, sumOp<label>());
1836 
1837  Info<< "Selected for direction " << vector::componentNames[dir]
1838  << " refinement : " << nCellsToRefine
1839  << " cells (out of " << mesh.globalData().nTotalCells()
1840  << ')' << endl;
1841 
1842  nAllRefine += nCellsToRefine;
1843 
1844  // Stop when no cells to refine or have done minimum necessary
1845  // iterations and not enough cells to refine.
1846  if (nCellsToRefine > 0)
1847  {
1848  if (debug)
1849  {
1850  const_cast<Time&>(mesh.time())++;
1851  }
1852 
1853  const bitSet isRefineCell(mesh.nCells(), cellsToRefine);
1854 
1855  autoPtr<mapPolyMesh> map
1856  (
1857  meshRefiner_.directionalRefine
1858  (
1859  "directional refinement iteration " + name(iter),
1860  dir,
1861  cellsToRefine
1862  )
1863  );
1864 
1865  Info<< "Refined mesh in = "
1866  << mesh.time().cpuTimeIncrement() << " s" << endl;
1867 
1869  (
1870  map().cellMap(),
1871  labelVector(0, 0, 0),
1872  dirCellLevel
1873  );
1874 
1875  // Note: edges will have been split. The points might have
1876  // inherited pointLevel from either side of the edge which
1877  // might not be the same for coupled edges so sync
1879  (
1880  mesh,
1881  pointLevel,
1882  maxEqOp<label>(),
1883  labelMin
1884  );
1885 
1886  forAll(map().cellMap(), celli)
1887  {
1888  if (isRefineCell[map().cellMap()[celli]])
1889  {
1890  dirCellLevel[celli][dir]++;
1891  }
1892  }
1893 
1894  // Do something with the pointLevel. See discussion about the
1895  // cellLevel. Do we keep min/max ?
1896  forAll(map().pointMap(), pointi)
1897  {
1898  label oldPointi = map().pointMap()[pointi];
1899  if (map().reversePointMap()[oldPointi] != pointi)
1900  {
1901  // Is added point (splitting an edge)
1902  pointLevel[pointi]++;
1903  }
1904  }
1905  }
1906  }
1907 
1908 
1909  if (nAllRefine == 0)
1910  {
1911  Info<< "Stopping refining since no cells selected."
1912  << nl << endl;
1913  break;
1914  }
1915 
1916  meshRefiner_.printMeshInfo
1917  (
1918  debug,
1919  "After directional refinement iteration " + name(iter)
1920  );
1921 
1923  {
1924  Pout<< "Writing directional refinement iteration "
1925  << iter << " mesh to time " << meshRefiner_.timeName() << endl;
1926  meshRefiner_.write
1927  (
1930  (
1933  ),
1934  mesh.time().path()/meshRefiner_.timeName()
1935  );
1936  }
1937  }
1938 
1939  // Adjust cellLevel from dirLevel? As max? Or the min?
1940  // For now: use max. The idea is that if there is a wall
1941  // any directional refinement is likely to be aligned with
1942  // the wall (wall layers) so any snapping/layering would probably
1943  // want to use this highest refinement level.
1944 
1945  forAll(cellLevel, celli)
1946  {
1947  cellLevel[celli] = cmptMax(dirCellLevel[celli]);
1948  }
1949 
1950  return iter;
1951 }
1952 
1953 
1954 void Foam::snappyRefineDriver::mergeAndSmoothRatio
1955 (
1956  const scalarList& allSeedPointDist,
1957  const label nSmoothExpansion,
1958  List<Tuple2<scalar, scalar>>& keyAndValue
1959 )
1960 {
1961  // Merge duplicate distance from coupled locations to get unique
1962  // distances to operate on, do on master
1963  SortableList<scalar> unmergedDist(allSeedPointDist);
1964  DynamicList<scalar> mergedDist;
1965 
1966  scalar prevDist = GREAT;
1967  forAll(unmergedDist, i)
1968  {
1969  scalar curDist = unmergedDist[i];
1970  scalar difference = mag(curDist - prevDist);
1971  if (difference > meshRefiner_.mergeDistance())
1972  //if (difference > 0.01)
1973  {
1974  mergedDist.append(curDist);
1975  prevDist = curDist;
1976  }
1977  }
1978 
1979  // Sort the unique distances
1980  SortableList<scalar> sortedDist(mergedDist);
1981  labelList indexSet = sortedDist.indices();
1982 
1983  // Get updated position starting from original (undistorted) mesh
1984  scalarList seedPointsNewLocation = sortedDist;
1985 
1986  scalar initResidual = 0.0;
1987  scalar prevIterResidual = GREAT;
1988 
1989  for (label iter = 0; iter < nSmoothExpansion; iter++)
1990  {
1991 
1992  // Position based edge averaging algorithm operated on
1993  // all seed plane locations in normalized form.
1994  //
1995  // 0 1 2 3 4 5 6 (edge numbers)
1996  // ---x---x---x---x---x---x---
1997  // 0 1 2 3 4 5 (point numbers)
1998  //
1999  // Average of edge 1-3 in terms of position
2000  // = (point3 - point0)/3
2001  // Keeping points 0-1 frozen, new position of point 2
2002  // = position2 + (average of edge 1-3 as above)
2003  for(label i = 2; i<mergedDist.size()-1; i++)
2004  {
2005  scalar oldX00 = sortedDist[i-2];
2006  scalar oldX1 = sortedDist[i+1];
2007  scalar curX0 = seedPointsNewLocation[i-1];
2008  seedPointsNewLocation[i] = curX0 + (oldX1 - oldX00)/3;
2009  }
2010 
2011  const scalarField residual(seedPointsNewLocation-sortedDist);
2012  {
2013  scalar res(sumMag(residual));
2014 
2015  if (iter == 0)
2016  {
2017  initResidual = res;
2018  }
2019  res /= initResidual;
2020 
2021  if (mag(prevIterResidual - res) < SMALL)
2022  {
2023  if (debug)
2024  {
2025  Pout<< "Converged with iteration " << iter
2026  << " initResidual: " << initResidual
2027  << " final residual : " << res << endl;
2028  }
2029  break;
2030  }
2031  else
2032  {
2033  prevIterResidual = res;
2034  }
2035  }
2036 
2037  // Update the field for next iteration, avoid moving points
2038  sortedDist = seedPointsNewLocation;
2039 
2040  }
2041 
2042  keyAndValue.setSize(mergedDist.size());
2043 
2044  forAll(mergedDist, i)
2045  {
2046  keyAndValue[i].first() = mergedDist[i];
2047  label index = indexSet[i];
2048  keyAndValue[i].second() = seedPointsNewLocation[index];
2049  }
2050 }
2051 
2052 
2053 Foam::label Foam::snappyRefineDriver::directionalSmooth
2054 (
2055  const refinementParameters& refineParams
2056 )
2057 {
2058  addProfiling(split, "snappyHexMesh::refine::smooth");
2059  Info<< nl
2060  << "Directional expansion ratio smoothing" << nl
2061  << "-------------------------------------" << nl
2062  << endl;
2063 
2064  fvMesh& baseMesh = meshRefiner_.mesh();
2065  const searchableSurfaces& geometry = meshRefiner_.surfaces().geometry();
2066  const shellSurfaces& shells = meshRefiner_.shells();
2067 
2068  label iter = 0;
2069 
2070  forAll(shells.nSmoothExpansion(), shellI)
2071  {
2072  if
2073  (
2074  shells.nSmoothExpansion()[shellI] > 0
2075  || shells.nSmoothPosition()[shellI] > 0
2076  )
2077  {
2078  label surfi = shells.shells()[shellI];
2079  const vector& userDirection = shells.smoothDirection()[shellI];
2080 
2081 
2082  // Extract inside points
2084  {
2085  // Get inside points
2086  List<volumeType> volType;
2087  geometry[surfi].getVolumeType(baseMesh.points(), volType);
2088 
2089  label nInside = 0;
2090  forAll(volType, pointi)
2091  {
2092  if (volType[pointi] == volumeType::INSIDE)
2093  {
2094  nInside++;
2095  }
2096  }
2097  pointLabels.setSize(nInside);
2098  nInside = 0;
2099  forAll(volType, pointi)
2100  {
2101  if (volType[pointi] == volumeType::INSIDE)
2102  {
2103  pointLabels[nInside++] = pointi;
2104  }
2105  }
2106 
2107  //bitSet isInsidePoint(baseMesh.nPoints());
2108  //forAll(volType, pointi)
2109  //{
2110  // if (volType[pointi] == volumeType::INSIDE)
2111  // {
2112  // isInsidePoint.set(pointi);
2113  // }
2114  //}
2115  //pointLabels = isInsidePoint.used();
2116  }
2117 
2118  // Mark all directed edges
2119  bitSet isXEdge(baseMesh.edges().size());
2120  {
2121  const edgeList& edges = baseMesh.edges();
2122  forAll(edges, edgei)
2123  {
2124  const edge& e = edges[edgei];
2125  vector eVec(e.vec(baseMesh.points()));
2126  eVec /= mag(eVec);
2127  if (mag(eVec&userDirection) > 0.9)
2128  {
2129  isXEdge.set(edgei);
2130  }
2131  }
2132  }
2133 
2134  // Get the extreme of smoothing region and
2135  // normalize all points within
2136  const scalar totalLength =
2137  geometry[surfi].bounds().span()
2138  & userDirection;
2139  const scalar startPosition =
2140  geometry[surfi].bounds().min()
2141  & userDirection;
2142 
2143  scalarField normalizedPosition(pointLabels.size(), Zero);
2144  forAll(pointLabels, i)
2145  {
2146  label pointi = pointLabels[i];
2147  normalizedPosition[i] =
2148  (
2149  ((baseMesh.points()[pointi]&userDirection) - startPosition)
2150  / totalLength
2151  );
2152  }
2153 
2154  // Sort the normalized position
2155  labelList order(sortedOrder(normalizedPosition));
2156 
2157  DynamicList<scalar> seedPointDist;
2158 
2159  // Select points from finest refinement (one point-per plane)
2160  scalar prevDist = GREAT;
2161  forAll(order, i)
2162  {
2163  label pointi = order[i];
2164  scalar curDist = normalizedPosition[pointi];
2165  if (mag(curDist - prevDist) > meshRefiner_.mergeDistance())
2166  {
2167  seedPointDist.append(curDist);
2168  prevDist = curDist;
2169  }
2170  }
2171 
2172  // Collect data from all processors
2173  scalarList allSeedPointDist;
2174  {
2175  List<scalarList> gatheredDist(Pstream::nProcs());
2176  gatheredDist[Pstream::myProcNo()] = seedPointDist;
2177  Pstream::gatherList(gatheredDist);
2178 
2179  // Combine processor lists into one big list.
2180  allSeedPointDist =
2181  ListListOps::combine<scalarList>
2182  (
2183  gatheredDist, accessOp<scalarList>()
2184  );
2185  }
2186 
2187  // Pre-set the points not to smooth (after expansion)
2188  bitSet isFrozenPoint(baseMesh.nPoints(), true);
2189 
2190  {
2191  scalar minSeed = min(allSeedPointDist);
2192  Pstream::scatter(minSeed);
2193  scalar maxSeed = max(allSeedPointDist);
2194  Pstream::scatter(maxSeed);
2195 
2196  forAll(normalizedPosition, posI)
2197  {
2198  const scalar pos = normalizedPosition[posI];
2199  if
2200  (
2201  (mag(pos-minSeed) < meshRefiner_.mergeDistance())
2202  || (mag(pos-maxSeed) < meshRefiner_.mergeDistance())
2203  )
2204  {
2205  // Boundary point: freeze
2206  isFrozenPoint.set(pointLabels[posI]);
2207  }
2208  else
2209  {
2210  // Internal to moving region
2211  isFrozenPoint.unset(pointLabels[posI]);
2212  }
2213  }
2214  }
2215 
2216  Info<< "Smoothing " << geometry[surfi].name() << ':' << nl
2217  << " Direction : " << userDirection << nl
2218  << " Number of points : "
2219  << returnReduce(pointLabels.size(), sumOp<label>())
2220  << " (out of " << baseMesh.globalData().nTotalPoints()
2221  << ")" << nl
2222  << " Smooth expansion iterations : "
2223  << shells.nSmoothExpansion()[shellI] << nl
2224  << " Smooth position iterations : "
2225  << shells.nSmoothPosition()[shellI] << nl
2226  << " Number of planes : "
2227  << allSeedPointDist.size()
2228  << endl;
2229 
2230  // Make lookup from original normalized distance to new value
2231  List<Tuple2<scalar, scalar>> keyAndValue(allSeedPointDist.size());
2232 
2233  // Filter unique seed distances and iterate for user given steps
2234  // or until convergence. Then get back map from old to new distance
2235  if (Pstream::master())
2236  {
2237  mergeAndSmoothRatio
2238  (
2239  allSeedPointDist,
2240  shells.nSmoothExpansion()[shellI],
2241  keyAndValue
2242  );
2243  }
2244 
2245  Pstream::scatter(keyAndValue);
2246 
2247  // Construct an iterpolation table for further queries
2248  // - although normalized values are used for query,
2249  // it might flow out of bounds due to precision, hence clamped
2250  const interpolationTable<scalar> table
2251  (
2252  keyAndValue,
2254  "undefined"
2255  );
2256 
2257  // Now move the points directly on the baseMesh.
2258  pointField baseNewPoints(baseMesh.points());
2259  forAll(pointLabels, i)
2260  {
2261  label pointi = pointLabels[i];
2262  const point& curPoint = baseMesh.points()[pointi];
2263  scalar curDist = normalizedPosition[i];
2264  scalar newDist = table(curDist);
2265  scalar newPosition = startPosition + newDist*totalLength;
2266  baseNewPoints[pointi] +=
2267  userDirection * (newPosition - (curPoint &userDirection));
2268  }
2269 
2270  // Moving base mesh with expansion ratio smoothing
2271  vectorField disp(baseNewPoints-baseMesh.points());
2273  (
2274  baseMesh,
2275  disp,
2276  maxMagSqrEqOp<vector>(),
2277  point::zero
2278  );
2279  baseMesh.movePoints(baseMesh.points()+disp);
2280 
2282  {
2283  const_cast<Time&>(baseMesh.time())++;
2284 
2285  Pout<< "Writing directional expansion ratio smoothed"
2286  << " mesh to time " << meshRefiner_.timeName() << endl;
2287 
2288  meshRefiner_.write
2289  (
2292  (
2295  ),
2296  baseMesh.time().path()/meshRefiner_.timeName()
2297  );
2298  }
2299 
2300  // Now we have moved the points in user specified region. Smooth
2301  // them with neighbour points to avoid skewed cells
2302  // Instead of moving actual mesh, operate on copy
2303  pointField baseMeshPoints(baseMesh.points());
2304  scalar initResidual = 0.0;
2305  scalar prevIterResidual = GREAT;
2306  for (iter = 0; iter < shells.nSmoothPosition()[shellI]; iter++)
2307  {
2308  {
2309  const edgeList& edges = baseMesh.edges();
2310  const labelListList& pointEdges = baseMesh.pointEdges();
2311 
2312  pointField unsmoothedPoints(baseMeshPoints);
2313 
2314  scalarField sumOther(baseMesh.nPoints(), Zero);
2315  labelList nSumOther(baseMesh.nPoints(), Zero);
2316  labelList nSumXEdges(baseMesh.nPoints(), Zero);
2317  forAll(edges, edgei)
2318  {
2319  const edge& e = edges[edgei];
2320  sumOther[e[0]] +=
2321  (unsmoothedPoints[e[1]]&userDirection);
2322  nSumOther[e[0]]++;
2323  sumOther[e[1]] +=
2324  (unsmoothedPoints[e[0]]&userDirection);
2325  nSumOther[e[1]]++;
2326  if (isXEdge[edgei])
2327  {
2328  nSumXEdges[e[0]]++;
2329  nSumXEdges[e[1]]++;
2330  }
2331  }
2332 
2334  (
2335  baseMesh,
2336  nSumXEdges,
2337  plusEqOp<label>(),
2338  label(0)
2339  );
2340 
2341  forAll(pointLabels, i)
2342  {
2343  label pointi = pointLabels[i];
2344 
2345  if (nSumXEdges[pointi] < 2)
2346  {
2347  // Hanging node. Remove the (single!) X edge so it
2348  // will follow points above or below instead
2349  const labelList& pEdges = pointEdges[pointi];
2350  forAll(pEdges, pE)
2351  {
2352  label edgei = pEdges[pE];
2353  if (isXEdge[edgei])
2354  {
2355  const edge& e = edges[edgei];
2356  label otherPt = e.otherVertex(pointi);
2357  nSumOther[pointi]--;
2358  sumOther[pointi] -=
2359  (
2360  unsmoothedPoints[otherPt]
2361  & userDirection
2362  );
2363  }
2364  }
2365  }
2366  }
2367 
2369  (
2370  baseMesh,
2371  sumOther,
2372  plusEqOp<scalar>(),
2373  scalar(0)
2374  );
2376  (
2377  baseMesh,
2378  nSumOther,
2379  plusEqOp<label>(),
2380  label(0)
2381  );
2382 
2383  forAll(pointLabels, i)
2384  {
2385  label pointi = pointLabels[i];
2386 
2387  if ((nSumOther[pointi] >= 2) && !isFrozenPoint[pointi])
2388  {
2389  scalar smoothPos =
2390  0.5
2391  *(
2392  (unsmoothedPoints[pointi]&userDirection)
2393  +sumOther[pointi]/nSumOther[pointi]
2394  );
2395 
2396  vector& v = baseNewPoints[pointi];
2397  v += (smoothPos-(v&userDirection))*userDirection;
2398  }
2399  }
2400 
2401  const vectorField residual(baseNewPoints - baseMeshPoints);
2402  {
2403  scalar res(gSum(mag(residual)));
2404 
2405  if (iter == 0)
2406  {
2407  initResidual = res;
2408  }
2409  res /= initResidual;
2410 
2411  if (mag(prevIterResidual - res) < SMALL)
2412  {
2413  Info<< "Converged smoothing in iteration " << iter
2414  << " initResidual: " << initResidual
2415  << " final residual : " << res << endl;
2416  break;
2417  }
2418  else
2419  {
2420  prevIterResidual = res;
2421  }
2422  }
2423 
2424  // Just copy new location instead of moving base mesh
2425  baseMeshPoints = baseNewPoints;
2426  }
2427  }
2428 
2429  // Move mesh to new location
2430  vectorField dispSmooth(baseMeshPoints-baseMesh.points());
2432  (
2433  baseMesh,
2434  dispSmooth,
2435  maxMagSqrEqOp<vector>(),
2436  point::zero
2437  );
2438  baseMesh.movePoints(baseMesh.points()+dispSmooth);
2439 
2441  {
2442  const_cast<Time&>(baseMesh.time())++;
2443 
2444  Pout<< "Writing positional smoothing iteration "
2445  << iter << " mesh to time " << meshRefiner_.timeName()
2446  << endl;
2447  meshRefiner_.write
2448  (
2451  (
2454  ),
2455  baseMesh.time().path()/meshRefiner_.timeName()
2456  );
2457  }
2458  }
2459  }
2460  return iter;
2461 }
2462 
2463 
2464 void Foam::snappyRefineDriver::baffleAndSplitMesh
2465 (
2466  const refinementParameters& refineParams,
2467  const snapParameters& snapParams,
2468  const bool handleSnapProblems,
2469  const dictionary& motionDict
2470 )
2471 {
2472  if (dryRun_)
2473  {
2474  return;
2475  }
2476 
2477  addProfiling(split, "snappyHexMesh::refine::splitting");
2478  Info<< nl
2479  << "Splitting mesh at surface intersections" << nl
2480  << "---------------------------------------" << nl
2481  << endl;
2482 
2483  const fvMesh& mesh = meshRefiner_.mesh();
2484 
2485  if (debug)
2486  {
2487  const_cast<Time&>(mesh.time())++;
2488  }
2489 
2490  // Introduce baffles at surface intersections. Note:
2491  // meshRefinement::surfaceIndex() will
2492  // be like boundary face from now on so not coupled anymore.
2493  meshRefiner_.baffleAndSplitMesh
2494  (
2495  handleSnapProblems, // detect&remove potential snap problem
2496 
2497  // Snap problem cell detection
2498  snapParams,
2499  refineParams.useTopologicalSnapDetection(),
2500  false, // perpendicular edge connected cells
2501  scalarField(0), // per region perpendicular angle
2502  refineParams.nErodeCellZone(),
2503 
2504  motionDict,
2505  const_cast<Time&>(mesh.time()),
2506  globalToMasterPatch_,
2507  globalToSlavePatch_,
2508  refineParams.locationsInMesh(),
2509  refineParams.zonesInMesh(),
2510  refineParams.locationsOutsideMesh(),
2511  setFormatter_
2512  );
2513 
2514 
2515  if (!handleSnapProblems) // merge free standing baffles?
2516  {
2517  meshRefiner_.mergeFreeStandingBaffles
2518  (
2519  snapParams,
2520  refineParams.useTopologicalSnapDetection(),
2521  false, // perpendicular edge connected cells
2522  scalarField(0), // per region perpendicular angle
2523  refineParams.planarAngle(),
2524  motionDict,
2525  const_cast<Time&>(mesh.time()),
2526  globalToMasterPatch_,
2527  globalToSlavePatch_,
2528  refineParams.locationsInMesh(),
2529  refineParams.locationsOutsideMesh(),
2530  setFormatter_
2531  );
2532  }
2533 }
2534 
2535 
2536 void Foam::snappyRefineDriver::zonify
2537 (
2538  const refinementParameters& refineParams,
2539  wordPairHashTable& zonesToFaceZone
2540 )
2541 {
2542  // Mesh is at its finest. Do zoning
2543  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2544  // This puts all faces with intersection across a zoneable surface
2545  // into that surface's faceZone. All cells inside faceZone get given the
2546  // same cellZone.
2547 
2548  const labelList namedSurfaces =
2549  surfaceZonesInfo::getNamedSurfaces(meshRefiner_.surfaces().surfZones());
2550 
2551  if
2552  (
2553  namedSurfaces.size()
2554  || refineParams.zonesInMesh().size()
2555  )
2556  {
2557  Info<< nl
2558  << "Introducing zones for interfaces" << nl
2559  << "--------------------------------" << nl
2560  << endl;
2561 
2562  const fvMesh& mesh = meshRefiner_.mesh();
2563 
2564  if (debug)
2565  {
2566  const_cast<Time&>(mesh.time())++;
2567  }
2568 
2569  meshRefiner_.zonify
2570  (
2571  refineParams.allowFreeStandingZoneFaces(),
2572  refineParams.nErodeCellZone(),
2573  refineParams.locationsInMesh(),
2574  refineParams.zonesInMesh(),
2575  zonesToFaceZone
2576  );
2577 
2579  {
2580  Pout<< "Writing zoned mesh to time "
2581  << meshRefiner_.timeName() << endl;
2582  meshRefiner_.write
2583  (
2586  (
2589  ),
2590  mesh.time().path()/meshRefiner_.timeName()
2591  );
2592  }
2593 
2594  // Check that all faces are synced
2596  }
2597 }
2598 
2599 
2600 void Foam::snappyRefineDriver::splitAndMergeBaffles
2601 (
2602  const refinementParameters& refineParams,
2603  const snapParameters& snapParams,
2604  const bool handleSnapProblems,
2605  const dictionary& motionDict
2606 )
2607 {
2608  if (dryRun_)
2609  {
2610  return;
2611  }
2612 
2613  Info<< nl
2614  << "Handling cells with snap problems" << nl
2615  << "---------------------------------" << nl
2616  << endl;
2617 
2618  const fvMesh& mesh = meshRefiner_.mesh();
2619 
2620  // Introduce baffles and split mesh
2621  if (debug)
2622  {
2623  const_cast<Time&>(mesh.time())++;
2624  }
2625 
2626  const scalarField& perpAngle = meshRefiner_.surfaces().perpendicularAngle();
2627 
2628  meshRefiner_.baffleAndSplitMesh
2629  (
2630  handleSnapProblems,
2631 
2632  // Snap problem cell detection
2633  snapParams,
2634  refineParams.useTopologicalSnapDetection(),
2635  handleSnapProblems, // remove perp edge connected cells
2636  perpAngle, // perp angle
2637  refineParams.nErodeCellZone(),
2638 
2639  motionDict,
2640  const_cast<Time&>(mesh.time()),
2641  globalToMasterPatch_,
2642  globalToSlavePatch_,
2643  refineParams.locationsInMesh(),
2644  refineParams.zonesInMesh(),
2645  refineParams.locationsOutsideMesh(),
2646  setFormatter_
2647  );
2648 
2649  // Merge free-standing baffles always
2650  meshRefiner_.mergeFreeStandingBaffles
2651  (
2652  snapParams,
2653  refineParams.useTopologicalSnapDetection(),
2654  handleSnapProblems,
2655  perpAngle,
2656  refineParams.planarAngle(),
2657  motionDict,
2658  const_cast<Time&>(mesh.time()),
2659  globalToMasterPatch_,
2660  globalToSlavePatch_,
2661  refineParams.locationsInMesh(),
2662  refineParams.locationsOutsideMesh(),
2663  setFormatter_
2664  );
2665 
2666  if (debug)
2667  {
2668  const_cast<Time&>(mesh.time())++;
2669  }
2670 
2671  // Duplicate points on baffles that are on more than one cell
2672  // region. This will help snapping pull them to separate surfaces.
2673  meshRefiner_.dupNonManifoldPoints();
2674 
2675 
2676  // Merge all baffles that are still remaining after duplicating points.
2677  List<labelPair> couples(localPointRegion::findDuplicateFacePairs(mesh));
2678 
2679  label nCouples = returnReduce(couples.size(), sumOp<label>());
2680 
2681  Info<< "Detected unsplittable baffles : " << nCouples << endl;
2682 
2683  if (nCouples > 0)
2684  {
2685  // Actually merge baffles. Note: not exactly parallellized. Should
2686  // convert baffle faces into processor faces if they resulted
2687  // from them.
2688  meshRefiner_.mergeBaffles(couples, Map<label>(0));
2689 
2690  if (debug)
2691  {
2692  // Debug:test all is still synced across proc patches
2693  meshRefiner_.checkData();
2694  }
2695 
2696  // Remove any now dangling parts
2697  meshRefiner_.splitMeshRegions
2698  (
2699  globalToMasterPatch_,
2700  globalToSlavePatch_,
2701  refineParams.locationsInMesh(),
2702  refineParams.locationsOutsideMesh(),
2703  setFormatter_
2704  );
2705 
2706  if (debug)
2707  {
2708  // Debug:test all is still synced across proc patches
2709  meshRefiner_.checkData();
2710  }
2711 
2712  Info<< "Merged free-standing baffles in = "
2713  << mesh.time().cpuTimeIncrement() << " s." << endl;
2714  }
2715 
2717  {
2718  Pout<< "Writing handleProblemCells mesh to time "
2719  << meshRefiner_.timeName() << endl;
2720  meshRefiner_.write
2721  (
2724  (
2727  ),
2728  mesh.time().path()/meshRefiner_.timeName()
2729  );
2730  }
2731 }
2732 
2733 
2736  meshRefinement& meshRefiner,
2737  const refinementParameters& refineParams,
2738  const HashTable<Pair<word>>& faceZoneToPatches
2739 )
2740 {
2741  if (faceZoneToPatches.size())
2742  {
2743  Info<< nl
2744  << "Adding patches for face zones" << nl
2745  << "-----------------------------" << nl
2746  << endl;
2747 
2748  Info<< setf(ios_base::left)
2749  << setw(6) << "Patch"
2750  << setw(20) << "Type"
2751  << setw(30) << "Name"
2752  << setw(30) << "FaceZone"
2753  << setw(10) << "FaceType"
2754  << nl
2755  << setw(6) << "-----"
2756  << setw(20) << "----"
2757  << setw(30) << "----"
2758  << setw(30) << "--------"
2759  << setw(10) << "--------"
2760  << endl;
2761 
2762  const polyMesh& mesh = meshRefiner.mesh();
2763 
2764  // Add patches for added inter-region faceZones
2765  forAllConstIters(faceZoneToPatches, iter)
2766  {
2767  const word& fzName = iter.key();
2768  const Pair<word>& patchNames = iter.val();
2769 
2770  // Get any user-defined faceZone data
2772  dictionary patchInfo = refineParams.getZoneInfo(fzName, fzType);
2773 
2774  const word& masterName = fzName;
2775  //const word slaveName = fzName + "_slave";
2776  //const word slaveName = czNames.second()+"_to_"+czNames.first();
2777  const word& slaveName = patchNames.second();
2778 
2779  label mpi = meshRefiner.addMeshedPatch(masterName, patchInfo);
2780 
2781  Info<< setf(ios_base::left)
2782  << setw(6) << mpi
2783  << setw(20) << mesh.boundaryMesh()[mpi].type()
2784  << setw(30) << masterName
2785  << setw(30) << fzName
2786  << setw(10) << surfaceZonesInfo::faceZoneTypeNames[fzType]
2787  << nl;
2788 
2789 
2790  label sli = meshRefiner.addMeshedPatch(slaveName, patchInfo);
2791 
2792  Info<< setf(ios_base::left)
2793  << setw(6) << sli
2794  << setw(20) << mesh.boundaryMesh()[sli].type()
2795  << setw(30) << slaveName
2796  << setw(30) << fzName
2797  << setw(10) << surfaceZonesInfo::faceZoneTypeNames[fzType]
2798  << nl;
2799 
2800  meshRefiner.addFaceZone(fzName, masterName, slaveName, fzType);
2801  }
2802 
2803  Info<< endl;
2804  }
2805 }
2806 
2807 
2808 void Foam::snappyRefineDriver::mergePatchFaces
2809 (
2810  const meshRefinement::FaceMergeType mergeType,
2811  const refinementParameters& refineParams,
2812  const dictionary& motionDict
2813 )
2814 {
2815  if (dryRun_)
2816  {
2817  return;
2818  }
2819 
2820  addProfiling(merge, "snappyHexMesh::refine::merge");
2821  Info<< nl
2822  << "Merge refined boundary faces" << nl
2823  << "----------------------------" << nl
2824  << endl;
2825 
2826  const fvMesh& mesh = meshRefiner_.mesh();
2827 
2828  if
2829  (
2830  mergeType == meshRefinement::FaceMergeType::GEOMETRIC
2831  || mergeType == meshRefinement::FaceMergeType::IGNOREPATCH
2832  )
2833  {
2834  meshRefiner_.mergePatchFacesUndo
2835  (
2836  Foam::cos(degToRad(45.0)),
2837  Foam::cos(degToRad(45.0)),
2838  meshRefiner_.meshedPatches(),
2839  motionDict,
2840  labelList(mesh.nFaces(), -1),
2841  mergeType
2842  );
2843  }
2844  else
2845  {
2846  // Still merge refined boundary faces if all four are on same patch
2847  meshRefiner_.mergePatchFaces
2848  (
2849  Foam::cos(degToRad(45.0)),
2850  Foam::cos(degToRad(45.0)),
2851  4, // only merge faces split into 4
2852  meshRefiner_.meshedPatches(),
2853  meshRefinement::FaceMergeType::GEOMETRIC // no merge across patches
2854  );
2855  }
2856 
2857  if (debug)
2858  {
2859  meshRefiner_.checkData();
2860  }
2861 
2862  meshRefiner_.mergeEdgesUndo(Foam::cos(degToRad(45.0)), motionDict);
2863 
2864  if (debug)
2865  {
2866  meshRefiner_.checkData();
2867  }
2868 }
2869 
2870 
2873  const dictionary& refineDict,
2874  const refinementParameters& refineParams,
2875  const snapParameters& snapParams,
2876  const bool prepareForSnapping,
2877  const meshRefinement::FaceMergeType mergeType,
2878  const dictionary& motionDict
2879 )
2880 {
2881  addProfiling(refine, "snappyHexMesh::refine");
2882  Info<< nl
2883  << "Refinement phase" << nl
2884  << "----------------" << nl
2885  << endl;
2886 
2887  const fvMesh& mesh = meshRefiner_.mesh();
2888 
2889 
2890  // Check that all the keep points are inside the mesh.
2891  refineParams.findCells(true, mesh, refineParams.locationsInMesh());
2892 
2893  // Check that all the keep points are inside the mesh.
2894  if (dryRun_)
2895  {
2896  refineParams.findCells(true, mesh, refineParams.locationsOutsideMesh());
2897  }
2898 
2899  // Estimate cell sizes
2900  if (dryRun_)
2901  {
2902  snappyVoxelMeshDriver voxelDriver
2903  (
2904  meshRefiner_,
2905  globalToMasterPatch_,
2906  globalToSlavePatch_
2907  );
2908  voxelDriver.doRefine(refineParams);
2909  }
2910 
2911 
2912  // Refine around feature edges
2913  featureEdgeRefine
2914  (
2915  refineParams,
2916  100, // maxIter
2917  0 // min cells to refine
2918  );
2919 
2920 
2921  // Initial automatic gap-level refinement: gaps smaller than the cell size
2922  if
2923  (
2924  max(meshRefiner_.surfaces().maxGapLevel()) > 0
2925  || max(meshRefiner_.shells().maxGapLevel()) > 0
2926  )
2927  {
2928  // In case we use automatic gap level refinement do some pre-refinement
2929  // (fast) since it is so slow.
2930 
2931  // Refine based on surface
2932  surfaceOnlyRefine
2933  (
2934  refineParams,
2935  20 // maxIter
2936  );
2937 
2938  // Refine cells that contain a gap
2939  smallFeatureRefine
2940  (
2941  refineParams,
2942  100 // maxIter
2943  );
2944  }
2945 
2946 
2947  // Refine based on surface
2948  surfaceOnlyRefine
2949  (
2950  refineParams,
2951  100 // maxIter
2952  );
2953 
2954  // Pass1 of automatic gap-level refinement: surface-intersected cells
2955  // in narrow gaps. Done early so we can remove the inside
2956  gapOnlyRefine
2957  (
2958  refineParams,
2959  100 // maxIter
2960  );
2961 
2962  // Remove cells inbetween two surfaces
2963  surfaceProximityBlock
2964  (
2965  refineParams,
2966  1 //100 // maxIter
2967  );
2968 
2969  // Remove cells (a certain distance) beyond surface intersections
2970  removeInsideCells
2971  (
2972  refineParams,
2973  1 // nBufferLayers
2974  );
2975 
2976  // Pass2 of automatic gap-level refinement: all cells in gaps
2977  bigGapOnlyRefine
2978  (
2979  refineParams,
2980  true, // spreadGapSize
2981  100 // maxIter
2982  );
2983 
2984  // Internal mesh refinement
2985  shellRefine
2986  (
2987  refineParams,
2988  100 // maxIter
2989  );
2990 
2991  // Remove any extra cells from limitRegion with level -1, without
2992  // adding any buffer layer this time
2993  removeInsideCells
2994  (
2995  refineParams,
2996  0 // nBufferLayers
2997  );
2998 
2999  // Refine any hexes with 5 or 6 faces refined to make smooth edges
3000  danglingCellRefine
3001  (
3002  refineParams,
3003  21, // 1 coarse face + 5 refined faces
3004  100 // maxIter
3005  );
3006  danglingCellRefine
3007  (
3008  refineParams,
3009  24, // 0 coarse faces + 6 refined faces
3010  100 // maxIter
3011  );
3012 
3013  // Refine any cells with differing refinement level on either side
3014  refinementInterfaceRefine
3015  (
3016  refineParams,
3017  10 // maxIter
3018  );
3019 
3020  // Directional shell refinement
3021  directionalShellRefine
3022  (
3023  refineParams,
3024  100 // maxIter
3025  );
3026 
3033  //surfaceProximityBlock
3034  //(
3035  // refineParams,
3036  // 1 //100 // maxIter
3037  //);
3038 
3039  if
3040  (
3041  max(meshRefiner_.shells().nSmoothExpansion()) > 0
3042  || max(meshRefiner_.shells().nSmoothPosition()) > 0
3043  )
3044  {
3045  directionalSmooth(refineParams);
3046  }
3047 
3048 
3049  // Introduce baffles at surface intersections. Remove sections unreachable
3050  // from keepPoint.
3051  baffleAndSplitMesh
3052  (
3053  refineParams,
3054  snapParams,
3055  prepareForSnapping,
3056  motionDict
3057  );
3058 
3059  // Mesh is at its finest. Do optional zoning (cellZones and faceZones)
3060  wordPairHashTable zonesToFaceZone;
3061  zonify(refineParams, zonesToFaceZone);
3062 
3063  // Create pairs of patches for faceZones
3064  {
3065  HashTable<Pair<word>> faceZoneToPatches(zonesToFaceZone.size());
3066 
3067  // Note: zonesToFaceZone contains the same data on different
3068  // processors but in different order. We could sort the
3069  // contents but instead just loop in sortedToc order.
3070  List<Pair<word>> czs(zonesToFaceZone.sortedToc());
3071 
3072  forAll(czs, i)
3073  {
3074  const Pair<word>& czNames = czs[i];
3075  const word& fzName = zonesToFaceZone[czNames];
3076 
3077  const word& masterName = fzName;
3078  const word slaveName = czNames.second() + "_to_" + czNames.first();
3079  Pair<word> patches(masterName, slaveName);
3080  faceZoneToPatches.insert(fzName, patches);
3081  }
3082  addFaceZones(meshRefiner_, refineParams, faceZoneToPatches);
3083  }
3084 
3085  // Pull baffles apart
3086  splitAndMergeBaffles
3087  (
3088  refineParams,
3089  snapParams,
3090  prepareForSnapping,
3091  motionDict
3092  );
3093 
3094  // Do something about cells with refined faces on the boundary
3095  if (prepareForSnapping)
3096  {
3097  mergePatchFaces(mergeType, refineParams, motionDict);
3098  }
3099 
3100 
3101  if (!dryRun_ && Pstream::parRun())
3102  {
3103  Info<< nl
3104  << "Doing final balancing" << nl
3105  << "---------------------" << nl
3106  << endl;
3107 
3108  // Do final balancing. Keep zoned faces on one processor since the
3109  // snap phase will convert them to baffles and this only works for
3110  // internal faces.
3111  meshRefiner_.balance
3112  (
3113  true, // keepZoneFaces
3114  false, // keepBaffles
3115  scalarField(mesh.nCells(), 1), // cellWeights
3116  decomposer_,
3117  distributor_
3118  );
3119  }
3120 }
3121 
3122 
3123 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
shellSurfaces.H
Foam::Pair::second
const T & second() const noexcept
Return second element, which is also the last element.
Definition: PairI.H:122
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::setf
Smanip< ios_base::fmtflags > setf(const ios_base::fmtflags flags)
Definition: IOmanip.H:169
profiling.H
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::HashTable::size
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::scalarList
List< scalar > scalarList
A List of scalars.
Definition: scalarList.H:64
Foam::refinementParameters::maxGlobalCells
label maxGlobalCells() const
Total number of cells.
Definition: refinementParameters.H:140
Foam::refinementParameters::maxLoadUnbalance
scalar maxLoadUnbalance() const
Allowed load unbalance.
Definition: refinementParameters.H:208
Foam::meshRefinement::WRITEMESH
Definition: meshRefinement.H:115
Foam::surfaceZonesInfo::faceZoneType
faceZoneType
What to do with faceZone faces.
Definition: surfaceZonesInfo.H:76
Foam::edgeList
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
Foam::labelMax
constexpr label labelMax
Definition: label.H:65
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::VectorSpace< Vector< label >, label, 3 >::uniform
static Vector< label > uniform(const label &s)
Return a VectorSpace with all elements = s.
Definition: VectorSpaceI.H:177
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::componentNames
static const char *const componentNames[]
Definition: VectorSpace.H:114
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const
Number of internal faces.
Definition: primitiveMeshI.H:78
fvMeshSubset.H
interface
interfaceProperties interface(alpha1, U, thermo->transportPropertiesDict())
Foam::refinementParameters::planarAngle
scalar planarAngle() const
Angle when two intersections are considered to be planar.
Definition: refinementParameters.H:164
Foam::primitiveMesh::nFaces
label nFaces() const
Number of mesh faces.
Definition: primitiveMeshI.H:90
Foam::labelPairList
List< labelPair > labelPairList
List of labelPairs.
Definition: labelPair.H:64
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:426
labelVector.H
Foam::meshRefinement::writeLevel
static writeType writeLevel()
Get/set write level.
Definition: meshRefinement.C:3395
Foam::meshRefinement::addFaceZone
label addFaceZone(const word &fzName, const word &masterPatch, const word &slavePatch, const surfaceZonesInfo::faceZoneType &fzType)
Add/lookup faceZone and update information. Return index of.
Definition: meshRefinement.C:2366
Foam::meshRefinement::REMOVE
set value to -1 any face that was refined
Definition: meshRefinement.H:129
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:414
localPointRegion.H
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:138
Foam::snappyVoxelMeshDriver::doRefine
void doRefine(const refinementParameters &refineParams)
Definition: snappyVoxelMeshDriver.C:460
Foam::globalMeshData::nTotalCells
label nTotalCells() const
Return total number of cells in decomposed mesh.
Definition: globalMeshData.H:394
unitConversion.H
Unit conversion functions.
Foam::refinementParameters::findCells
static labelList findCells(const bool checkInsideMesh, const polyMesh &, const pointField &locations)
Checks that cells are in mesh. Returns cells (or -1) they.
Definition: refinementParameters.C:209
Foam::sumMag
dimensioned< typename typeOfMag< Type >::type > sumMag(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:332
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
Definition: gatherScatter.C:150
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:72
Foam::surfaceZonesInfo::getNamedSurfaces
static labelList getNamedSurfaces(const PtrList< surfaceZonesInfo > &surfList)
Get indices of named surfaces (surfaces with faceZoneName)
Definition: surfaceZonesInfo.C:192
interpolationTable.H
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:435
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::gSum
Type gSum(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:594
Foam::meshRefinement::balanceAndRefine
autoPtr< mapDistributePolyMesh > balanceAndRefine(const string &msg, decompositionMethod &decomposer, fvMeshDistribute &distributor, const labelList &cellsToRefine, const scalar maxLoadUnbalance)
Balance before refining some cells.
Definition: meshRefinementRefine.C:2483
refinementFeatures.H
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::meshRefinement::refineAndBalance
autoPtr< mapDistributePolyMesh > refineAndBalance(const string &msg, decompositionMethod &decomposer, fvMeshDistribute &distributor, const labelList &cellsToRefine, const scalar maxLoadUnbalance)
Refine some cells and rebalance.
Definition: meshRefinementRefine.C:2382
Foam::labelIOList
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:44
Foam::meshRefinement::mesh
const fvMesh & mesh() const
Reference to mesh.
Definition: meshRefinement.H:940
syncTools.H
Foam::hexRef8::consistentRefinement
labelList consistentRefinement(const labelUList &cellLevel, const labelList &cellsToRefine, const bool maxSet) const
Given valid mesh and current cell level and proposed.
Definition: hexRef8.C:2257
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::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::meshRefinement::updateList
static void updateList(const labelList &newToOld, const T &nullValue, List< T > &elems)
Helper: reorder list according to map.
Definition: meshRefinementTemplates.C:38
Foam::syncTools::syncPointList
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
Definition: syncToolsTemplates.C:747
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::meshRefinement::FaceMergeType
FaceMergeType
Enumeration for what to do with co-planar patch faces on a single.
Definition: meshRefinement.H:134
Foam::meshRefinement::refineCandidates
labelList refineCandidates(const pointField &keepPoints, const scalar curvature, const scalar planarAngle, const bool featureRefinement, const bool featureDistanceRefinement, const bool internalRefinement, const bool surfaceRefinement, const bool curvatureRefinement, const bool smallFeatureRefinement, const bool gapRefinement, const bool bigGapRefinement, const bool spreadGapSize, const label maxGlobalCells, const label maxLocalCells) const
Calculate list of cells to refine.
Definition: meshRefinementRefine.C:2032
Foam::labelVector
Vector< label > labelVector
Vector of labels.
Definition: labelVector.H:51
Foam::cmptMax
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:253
searchableSurfaces.H
mapDistributePolyMesh.H
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::snapParameters
Simple container to keep together snap specific information.
Definition: snapParameters.H:52
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
snappyVoxelMeshDriver.H
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::meshRefinement::checkCoupledFaceZones
static void checkCoupledFaceZones(const polyMesh &)
Helper function: check that face zones are synced.
Definition: meshRefinement.C:1969
Foam::refinementParameters::maxLocalCells
label maxLocalCells() const
Per processor max number of cells.
Definition: refinementParameters.H:146
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
refinementSurfaces.H
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1076
Foam::cellList
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:47
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::refinementParameters
Simple container to keep together refinement specific information.
Definition: refinementParameters.H:58
Foam::refinementParameters::curvature
scalar curvature() const
Curvature.
Definition: refinementParameters.H:158
patchNames
wordList patchNames(nPatches)
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::syncTools::swapBoundaryCellList
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
Definition: syncToolsTemplates.C:1175
Foam::bounds::normalBounding::CLAMP
Clamp value to the start/end value.
addProfiling
#define addProfiling(name, descr)
Define profiling trigger with specified name and description string.
Definition: profilingTrigger.H:114
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::snappyRefineDriver::doRefine
void doRefine(const dictionary &refineDict, const refinementParameters &refineParams, const snapParameters &snapParams, const bool prepareForSnapping, const meshRefinement::FaceMergeType mergeType, const dictionary &motionDict)
Do all the refinement.
Definition: snappyRefineDriver.C:2872
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
meshRefinement.H
Foam::decompositionMethod
Abstract base class for domain decomposition.
Definition: decompositionMethod.H:51
Foam::writer< scalar >
Foam::refinementParameters::locationsOutsideMesh
const pointField & locationsOutsideMesh() const
Optional points which are checked to be outside the mesh.
Definition: refinementParameters.H:188
snappyRefineDriver.H
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::setw
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::HashTable::sortedToc
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:136
Foam::degToRad
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Definition: unitConversion.H:48
Foam::snappyVoxelMeshDriver
Equivalent of snappyRefineDriver but operating on a voxel mesh.
Definition: snappyVoxelMeshDriver.H:60
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:444
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:438
Foam::HashTable
A HashTable similar to std::unordered_map.
Definition: HashTable.H:105
Foam::meshRefinement::features
const refinementFeatures & features() const
Reference to feature edge mesh.
Definition: meshRefinement.H:973
Foam::meshRefinement::meshCutter
const hexRef8 & meshCutter() const
Reference to meshcutting engine.
Definition: meshRefinement.H:991
Foam::surfaceZonesInfo::faceZoneTypeNames
static const Enum< faceZoneType > faceZoneTypeNames
Definition: surfaceZonesInfo.H:83
Time.H
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::wordPairHashTable
HashTable< word, Pair< word >, FixedList< word, 2 >::Hash<> > wordPairHashTable
HashTable of Pair<word>
Definition: wordPairHashTable.H:51
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::Pair< word >
Foam::Time::path
fileName path() const
Return path.
Definition: Time.H:303
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
refinementParameters.H
Foam::meshRefinement::writeType
writeType
Enumeration for what to write. Used as a bit-pattern.
Definition: meshRefinement.H:113
Foam::refinementParameters::getZoneInfo
dictionary getZoneInfo(const word &fzName, surfaceZonesInfo::faceZoneType &faceType) const
Get patchInfo and faceType for faceZone.
Definition: refinementParameters.C:158
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:102
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::meshRefinement
Helper class which maintains intersections of (changing) mesh with (static) surfaces.
Definition: meshRefinement.H:86
Foam::UList< label >
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::direction
uint8_t direction
Definition: direction.H:47
Foam::meshRefinement::addMeshedPatch
label addMeshedPatch(const word &name, const dictionary &)
Add patch originating from meshing. Update meshedPatches_.
Definition: meshRefinement.C:2289
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
snapParameters.H
Foam::volumeType::INSIDE
A location inside the volume.
Definition: volumeType.H:68
Foam::snappyRefineDriver::addFaceZones
static void addFaceZones(meshRefinement &meshRefiner, const refinementParameters &refineParams, const HashTable< Pair< word >> &faceZoneToPatches)
Helper: add faceZones and patches.
Definition: snappyRefineDriver.C:2735
Foam::labelMin
constexpr label labelMin
Definition: label.H:64
split
static bool split(const std::string &line, std::string &key, std::string &val)
Definition: cpuInfo.C:39
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::cpuTimeCxx::cpuTimeIncrement
double cpuTimeIncrement() const
Return CPU time (in seconds) since last call to cpuTimeIncrement()
Definition: cpuTimeCxx.C:75
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:246
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::zero
static const Vector< scalar > zero
Definition: VectorSpace.H:115
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::sortedOrder
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
cellSet.H
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1241
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::fvMeshDistribute
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
Definition: fvMeshDistribute.H:73
pointLabels
labelList pointLabels(nPoints, -1)
Foam::refinementParameters::locationsInMesh
const pointField & locationsInMesh() const
Areas to keep.
Definition: refinementParameters.H:176
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1082
Foam::meshRefinement::MESH
Definition: meshRefinement.H:95
Foam::refinementParameters::minRefineCells
label minRefineCells() const
When to stop refining.
Definition: refinementParameters.H:152
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::nComponents
static constexpr direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:101
Foam::localPointRegion::findDuplicateFacePairs
static labelPairList findDuplicateFacePairs(const polyMesh &)
Helper routine to find all baffles (two boundary faces.
Definition: localPointRegion.C:625
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177
Foam::meshRefinement::debugType
debugType
Enumeration for what to debug. Used as a bit-pattern.
Definition: meshRefinement.H:93
Foam::primitiveMesh::faceAreas
const vectorField & faceAreas() const
Definition: primitiveMeshFaceCentresAndAreas.C:156