autoRefineDriver.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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "autoRefineDriver.H"
27 #include "meshRefinement.H"
28 #include "fvMesh.H"
29 #include "Time.H"
30 #include "cellSet.H"
31 #include "syncTools.H"
32 #include "refinementParameters.H"
33 #include "refinementSurfaces.H"
34 #include "refinementFeatures.H"
35 #include "shellSurfaces.H"
36 #include "mapDistributePolyMesh.H"
37 #include "unitConversion.H"
38 #include "snapParameters.H"
39 #include "localPointRegion.H"
40 #include "IOmanip.H"
41 #include "labelVector.H"
42 
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 
45 namespace Foam
46 {
47 
48 defineTypeNameAndDebug(autoRefineDriver, 0);
49 
50 } // End namespace Foam
51 
52 
53 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
54 
55 // Construct from components
57 (
58  meshRefinement& meshRefiner,
59  decompositionMethod& decomposer,
60  fvMeshDistribute& distributor,
61  const labelList& globalToMasterPatch,
62  const labelList& globalToSlavePatch
63 )
64 :
65  meshRefiner_(meshRefiner),
66  decomposer_(decomposer),
67  distributor_(distributor),
68  globalToMasterPatch_(globalToMasterPatch),
69  globalToSlavePatch_(globalToSlavePatch)
70 {}
71 
72 
73 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
74 
76 (
77  const refinementParameters& refineParams,
78  const label maxIter,
79  const label minRefine
80 )
81 {
82  const fvMesh& mesh = meshRefiner_.mesh();
83 
84  label iter = 0;
85 
86  if (meshRefiner_.features().size() && maxIter > 0)
87  {
88  for (; iter < maxIter; iter++)
89  {
90  Info<< nl
91  << "Feature refinement iteration " << iter << nl
92  << "------------------------------" << nl
93  << endl;
94 
95  labelList candidateCells
96  (
97  meshRefiner_.refineCandidates
98  (
99  refineParams.locationsInMesh(),
100  refineParams.curvature(),
101  refineParams.planarAngle(),
102 
103  true, // featureRefinement
104  false, // featureDistanceRefinement
105  false, // internalRefinement
106  false, // surfaceRefinement
107  false, // curvatureRefinement
108  false, // smallFeatureRefinement
109  false, // gapRefinement
110  false, // bigGapRefinement
111  false, // spreadGapSize
112  refineParams.maxGlobalCells(),
113  refineParams.maxLocalCells()
114  )
115  );
116  labelList cellsToRefine
117  (
118  meshRefiner_.meshCutter().consistentRefinement
119  (
120  candidateCells,
121  true
122  )
123  );
124  Info<< "Determined cells to refine in = "
125  << mesh.time().cpuTimeIncrement() << " s" << endl;
126 
127 
128 
129  label nCellsToRefine = cellsToRefine.size();
130  reduce(nCellsToRefine, sumOp<label>());
131 
132  Info<< "Selected for feature refinement : " << nCellsToRefine
133  << " cells (out of " << mesh.globalData().nTotalCells()
134  << ')' << endl;
135 
136  if (nCellsToRefine <= minRefine)
137  {
138  Info<< "Stopping refining since too few cells selected."
139  << nl << endl;
140  break;
141  }
142 
143 
144  if (debug > 0)
145  {
146  const_cast<Time&>(mesh.time())++;
147  }
148 
149 
150  if
151  (
153  (
154  (mesh.nCells() >= refineParams.maxLocalCells()),
155  orOp<bool>()
156  )
157  )
158  {
159  meshRefiner_.balanceAndRefine
160  (
161  "feature refinement iteration " + name(iter),
162  decomposer_,
163  distributor_,
164  cellsToRefine,
165  refineParams.maxLoadUnbalance()
166  );
167  }
168  else
169  {
170  meshRefiner_.refineAndBalance
171  (
172  "feature refinement iteration " + name(iter),
173  decomposer_,
174  distributor_,
175  cellsToRefine,
176  refineParams.maxLoadUnbalance()
177  );
178  }
179  }
180  }
181  return iter;
182 }
183 
184 
186 (
187  const refinementParameters& refineParams,
188  const label maxIter
189 )
190 {
191  const fvMesh& mesh = meshRefiner_.mesh();
192 
193 
194  label iter = 0;
195 
196  // See if any surface has an extendedGapLevel
197  labelList surfaceMaxLevel(meshRefiner_.surfaces().maxGapLevel());
198  labelList shellMaxLevel(meshRefiner_.shells().maxGapLevel());
199 
200  if (max(surfaceMaxLevel) == 0 && max(shellMaxLevel) == 0)
201  {
202  return iter;
203  }
204 
205  for (; iter < maxIter; iter++)
206  {
207  Info<< nl
208  << "Small surface feature refinement iteration " << iter << nl
209  << "--------------------------------------------" << nl
210  << endl;
211 
212 
213  // Determine cells to refine
214  // ~~~~~~~~~~~~~~~~~~~~~~~~~
215 
216  labelList candidateCells
217  (
218  meshRefiner_.refineCandidates
219  (
220  refineParams.locationsInMesh(),
221  refineParams.curvature(),
222  refineParams.planarAngle(),
223 
224  false, // featureRefinement
225  false, // featureDistanceRefinement
226  false, // internalRefinement
227  false, // surfaceRefinement
228  false, // curvatureRefinement
229  true, // smallFeatureRefinement
230  false, // gapRefinement
231  false, // bigGapRefinement
232  false, // spreadGapSize
233  refineParams.maxGlobalCells(),
234  refineParams.maxLocalCells()
235  )
236  );
237 
238  labelList cellsToRefine
239  (
240  meshRefiner_.meshCutter().consistentRefinement
241  (
242  candidateCells,
243  true
244  )
245  );
246  Info<< "Determined cells to refine in = "
247  << mesh.time().cpuTimeIncrement() << " s" << endl;
248 
249 
250  label nCellsToRefine = cellsToRefine.size();
251  reduce(nCellsToRefine, sumOp<label>());
252 
253  Info<< "Selected for refinement : " << nCellsToRefine
254  << " cells (out of " << mesh.globalData().nTotalCells()
255  << ')' << endl;
256 
257  // Stop when no cells to refine or have done minimum necessary
258  // iterations and not enough cells to refine.
259  if (nCellsToRefine == 0)
260  {
261  Info<< "Stopping refining since too few cells selected."
262  << nl << endl;
263  break;
264  }
265 
266 
267  if (debug)
268  {
269  const_cast<Time&>(mesh.time())++;
270  }
271 
272 
273  if
274  (
276  (
277  (mesh.nCells() >= refineParams.maxLocalCells()),
278  orOp<bool>()
279  )
280  )
281  {
282  meshRefiner_.balanceAndRefine
283  (
284  "small feature refinement iteration " + name(iter),
285  decomposer_,
286  distributor_,
287  cellsToRefine,
288  refineParams.maxLoadUnbalance()
289  );
290  }
291  else
292  {
293  meshRefiner_.refineAndBalance
294  (
295  "small feature refinement iteration " + name(iter),
296  decomposer_,
297  distributor_,
298  cellsToRefine,
299  refineParams.maxLoadUnbalance()
300  );
301  }
302  }
303  return iter;
304 }
305 
306 
308 (
309  const refinementParameters& refineParams,
310  const label maxIter
311 )
312 {
313  const fvMesh& mesh = meshRefiner_.mesh();
314 
315  // Determine the maximum refinement level over all surfaces. This
316  // determines the minumum number of surface refinement iterations.
317  label overallMaxLevel = max(meshRefiner_.surfaces().maxLevel());
318 
319  label iter;
320  for (iter = 0; iter < maxIter; iter++)
321  {
322  Info<< nl
323  << "Surface refinement iteration " << iter << nl
324  << "------------------------------" << nl
325  << endl;
326 
327 
328  // Determine cells to refine
329  // ~~~~~~~~~~~~~~~~~~~~~~~~~
330  // Only look at surface intersections (minLevel and surface curvature),
331  // do not do internal refinement (refinementShells)
332 
333  labelList candidateCells
334  (
335  meshRefiner_.refineCandidates
336  (
337  refineParams.locationsInMesh(),
338  refineParams.curvature(),
339  refineParams.planarAngle(),
340 
341  false, // featureRefinement
342  false, // featureDistanceRefinement
343  false, // internalRefinement
344  true, // surfaceRefinement
345  true, // curvatureRefinement
346  false, // smallFeatureRefinement
347  false, // gapRefinement
348  false, // bigGapRefinement
349  false, // spreadGapSize
350  refineParams.maxGlobalCells(),
351  refineParams.maxLocalCells()
352  )
353  );
354  labelList cellsToRefine
355  (
356  meshRefiner_.meshCutter().consistentRefinement
357  (
358  candidateCells,
359  true
360  )
361  );
362  Info<< "Determined cells to refine in = "
363  << mesh.time().cpuTimeIncrement() << " s" << endl;
364 
365 
366  label nCellsToRefine = cellsToRefine.size();
367  reduce(nCellsToRefine, sumOp<label>());
368 
369  Info<< "Selected for refinement : " << nCellsToRefine
370  << " cells (out of " << mesh.globalData().nTotalCells()
371  << ')' << endl;
372 
373  // Stop when no cells to refine or have done minimum necessary
374  // iterations and not enough cells to refine.
375  if
376  (
377  nCellsToRefine == 0
378  || (
379  iter >= overallMaxLevel
380  && nCellsToRefine <= refineParams.minRefineCells()
381  )
382  )
383  {
384  Info<< "Stopping refining since too few cells selected."
385  << nl << endl;
386  break;
387  }
388 
389 
390  if (debug)
391  {
392  const_cast<Time&>(mesh.time())++;
393  }
394 
395 
396  if
397  (
399  (
400  (mesh.nCells() >= refineParams.maxLocalCells()),
401  orOp<bool>()
402  )
403  )
404  {
405  meshRefiner_.balanceAndRefine
406  (
407  "surface refinement iteration " + name(iter),
408  decomposer_,
409  distributor_,
410  cellsToRefine,
411  refineParams.maxLoadUnbalance()
412  );
413  }
414  else
415  {
416  meshRefiner_.refineAndBalance
417  (
418  "surface refinement iteration " + name(iter),
419  decomposer_,
420  distributor_,
421  cellsToRefine,
422  refineParams.maxLoadUnbalance()
423  );
424  }
425  }
426  return iter;
427 }
428 
429 
431 (
432  const refinementParameters& refineParams,
433  const label maxIter
434 )
435 {
436  const fvMesh& mesh = meshRefiner_.mesh();
437 
438  // Determine the maximum refinement level over all surfaces. This
439  // determines the minumum number of surface refinement iterations.
440 
441  label maxIncrement = 0;
442  const labelList& maxLevel = meshRefiner_.surfaces().maxLevel();
443  const labelList& gapLevel = meshRefiner_.surfaces().gapLevel();
444 
445  forAll(maxLevel, i)
446  {
447  maxIncrement = max(maxIncrement, gapLevel[i]-maxLevel[i]);
448  }
449 
450  label iter = 0;
451 
452  if (maxIncrement == 0)
453  {
454  return iter;
455  }
456 
457  for (iter = 0; iter < maxIter; iter++)
458  {
459  Info<< nl
460  << "Gap refinement iteration " << iter << nl
461  << "--------------------------" << nl
462  << endl;
463 
464 
465  // Determine cells to refine
466  // ~~~~~~~~~~~~~~~~~~~~~~~~~
467  // Only look at surface intersections (minLevel and surface curvature),
468  // do not do internal refinement (refinementShells)
469 
470  labelList candidateCells
471  (
472  meshRefiner_.refineCandidates
473  (
474  refineParams.locationsInMesh(),
475  refineParams.curvature(),
476  refineParams.planarAngle(),
477 
478  false, // featureRefinement
479  false, // featureDistanceRefinement
480  false, // internalRefinement
481  false, // surfaceRefinement
482  false, // curvatureRefinement
483  false, // smallFeatureRefinement
484  true, // gapRefinement
485  false, // bigGapRefinement
486  false, // spreadGapSize
487  refineParams.maxGlobalCells(),
488  refineParams.maxLocalCells()
489  )
490  );
491 
492  if (debug&meshRefinement::MESH)
493  {
494  Pout<< "Dumping " << candidateCells.size()
495  << " cells to cellSet candidateCellsFromGap." << endl;
496  cellSet c(mesh, "candidateCellsFromGap", candidateCells);
497  c.instance() = meshRefiner_.timeName();
498  c.write();
499  }
500 
501  // Grow by one layer to make sure we're covering the gap
502  {
503  boolList isCandidateCell(mesh.nCells(), false);
504  forAll(candidateCells, i)
505  {
506  isCandidateCell[candidateCells[i]] = true;
507  }
508 
509  for (label i=0; i<1; i++)
510  {
511  boolList newIsCandidateCell(isCandidateCell);
512 
513  // Internal faces
514  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
515  {
516  label own = mesh.faceOwner()[faceI];
517  label nei = mesh.faceNeighbour()[faceI];
518 
519  if (isCandidateCell[own] != isCandidateCell[nei])
520  {
521  newIsCandidateCell[own] = true;
522  newIsCandidateCell[nei] = true;
523  }
524  }
525 
526  // Get coupled boundary condition values
527  boolList neiIsCandidateCell;
528  syncTools::swapBoundaryCellList
529  (
530  mesh,
531  isCandidateCell,
532  neiIsCandidateCell
533  );
534 
535  // Boundary faces
536  for
537  (
538  label faceI = mesh.nInternalFaces();
539  faceI < mesh.nFaces();
540  faceI++
541  )
542  {
543  label own = mesh.faceOwner()[faceI];
544  label bFaceI = faceI-mesh.nInternalFaces();
545 
546  if (isCandidateCell[own] != neiIsCandidateCell[bFaceI])
547  {
548  newIsCandidateCell[own] = true;
549  }
550  }
551 
552  isCandidateCell.transfer(newIsCandidateCell);
553  }
554 
555  label n = 0;
556  forAll(isCandidateCell, cellI)
557  {
558  if (isCandidateCell[cellI])
559  {
560  n++;
561  }
562  }
563  candidateCells.setSize(n);
564  n = 0;
565  forAll(isCandidateCell, cellI)
566  {
567  if (isCandidateCell[cellI])
568  {
569  candidateCells[n++] = cellI;
570  }
571  }
572  }
573 
574 
575  if (debug&meshRefinement::MESH)
576  {
577  Pout<< "Dumping " << candidateCells.size()
578  << " cells to cellSet candidateCellsFromGapPlusBuffer." << endl;
579  cellSet c(mesh, "candidateCellsFromGapPlusBuffer", candidateCells);
580  c.instance() = meshRefiner_.timeName();
581  c.write();
582  }
583 
584 
585  labelList cellsToRefine
586  (
587  meshRefiner_.meshCutter().consistentRefinement
588  (
589  candidateCells,
590  true
591  )
592  );
593  Info<< "Determined cells to refine in = "
594  << mesh.time().cpuTimeIncrement() << " s" << endl;
595 
596 
597  label nCellsToRefine = cellsToRefine.size();
598  reduce(nCellsToRefine, sumOp<label>());
599 
600  Info<< "Selected for refinement : " << nCellsToRefine
601  << " cells (out of " << mesh.globalData().nTotalCells()
602  << ')' << endl;
603 
604  // Stop when no cells to refine or have done minimum necessary
605  // iterations and not enough cells to refine.
606  if
607  (
608  nCellsToRefine == 0
609  || (
610  iter >= maxIncrement
611  && nCellsToRefine <= refineParams.minRefineCells()
612  )
613  )
614  {
615  Info<< "Stopping refining since too few cells selected."
616  << nl << endl;
617  break;
618  }
619 
620 
621  if (debug)
622  {
623  const_cast<Time&>(mesh.time())++;
624  }
625 
626 
627  if
628  (
630  (
631  (mesh.nCells() >= refineParams.maxLocalCells()),
632  orOp<bool>()
633  )
634  )
635  {
636  meshRefiner_.balanceAndRefine
637  (
638  "gap refinement iteration " + name(iter),
639  decomposer_,
640  distributor_,
641  cellsToRefine,
642  refineParams.maxLoadUnbalance()
643  );
644  }
645  else
646  {
647  meshRefiner_.refineAndBalance
648  (
649  "gap refinement iteration " + name(iter),
650  decomposer_,
651  distributor_,
652  cellsToRefine,
653  refineParams.maxLoadUnbalance()
654  );
655  }
656  }
657  return iter;
658 }
659 
660 
662 (
663  const refinementParameters& refineParams,
664  const bool spreadGapSize,
665  const label maxIter
666 )
667 {
668  const fvMesh& mesh = meshRefiner_.mesh();
669 
670  label iter = 0;
671 
672  // See if any surface has an extendedGapLevel
673  labelList surfaceMaxLevel(meshRefiner_.surfaces().maxGapLevel());
674  labelList shellMaxLevel(meshRefiner_.shells().maxGapLevel());
675 
676  label overallMaxLevel(max(max(surfaceMaxLevel), max(shellMaxLevel)));
677 
678  if (overallMaxLevel == 0)
679  {
680  return iter;
681  }
682 
683 
684  for (; iter < maxIter; iter++)
685  {
686  Info<< nl
687  << "Big gap refinement iteration " << iter << nl
688  << "------------------------------" << nl
689  << endl;
690 
691 
692  // Determine cells to refine
693  // ~~~~~~~~~~~~~~~~~~~~~~~~~
694 
695  labelList candidateCells
696  (
697  meshRefiner_.refineCandidates
698  (
699  refineParams.locationsInMesh(),
700  refineParams.curvature(),
701  refineParams.planarAngle(),
702 
703  false, // featureRefinement
704  false, // featureDistanceRefinement
705  false, // internalRefinement
706  false, // surfaceRefinement
707  false, // curvatureRefinement
708  false, // smallFeatureRefinement
709  false, // gapRefinement
710  true, // bigGapRefinement
711  spreadGapSize, // spreadGapSize
712  refineParams.maxGlobalCells(),
713  refineParams.maxLocalCells()
714  )
715  );
716 
717 
718  if (debug&meshRefinement::MESH)
719  {
720  Pout<< "Dumping " << candidateCells.size()
721  << " cells to cellSet candidateCellsFromBigGap." << endl;
722  cellSet c(mesh, "candidateCellsFromBigGap", candidateCells);
723  c.instance() = meshRefiner_.timeName();
724  c.write();
725  }
726 
727  labelList cellsToRefine
728  (
729  meshRefiner_.meshCutter().consistentRefinement
730  (
731  candidateCells,
732  true
733  )
734  );
735  Info<< "Determined cells to refine in = "
736  << mesh.time().cpuTimeIncrement() << " s" << endl;
737 
738 
739  label nCellsToRefine = cellsToRefine.size();
740  reduce(nCellsToRefine, sumOp<label>());
741 
742  Info<< "Selected for refinement : " << nCellsToRefine
743  << " cells (out of " << mesh.globalData().nTotalCells()
744  << ')' << endl;
745 
746  // Stop when no cells to refine or have done minimum necessary
747  // iterations and not enough cells to refine.
748  if
749  (
750  nCellsToRefine == 0
751  || (
752  iter >= overallMaxLevel
753  && nCellsToRefine <= refineParams.minRefineCells()
754  )
755  )
756  {
757  Info<< "Stopping refining since too few cells selected."
758  << nl << endl;
759  break;
760  }
761 
762 
763  if (debug)
764  {
765  const_cast<Time&>(mesh.time())++;
766  }
767 
768 
769  if
770  (
772  (
773  (mesh.nCells() >= refineParams.maxLocalCells()),
774  orOp<bool>()
775  )
776  )
777  {
778  meshRefiner_.balanceAndRefine
779  (
780  "big gap refinement iteration " + name(iter),
781  decomposer_,
782  distributor_,
783  cellsToRefine,
784  refineParams.maxLoadUnbalance()
785  );
786  }
787  else
788  {
789  meshRefiner_.refineAndBalance
790  (
791  "big gap refinement iteration " + name(iter),
792  decomposer_,
793  distributor_,
794  cellsToRefine,
795  refineParams.maxLoadUnbalance()
796  );
797  }
798  }
799  return iter;
800 }
801 
802 
804 (
805  const refinementParameters& refineParams,
806  const label nFaces,
807  const label maxIter
808 )
809 {
810  const fvMesh& mesh = meshRefiner_.mesh();
811 
812  label iter;
813  for (iter = 0; iter < maxIter; iter++)
814  {
815  Info<< nl
816  << "Dangling coarse cells refinement iteration " << iter << nl
817  << "--------------------------------------------" << nl
818  << endl;
819 
820 
821  // Determine cells to refine
822  // ~~~~~~~~~~~~~~~~~~~~~~~~~
823 
824  const cellList& cells = mesh.cells();
825  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
826 
827  labelList candidateCells;
828  {
829  cellSet candidateCellSet(mesh, "candidateCells", cells.size()/1000);
830 
831  forAll(cells, cellI)
832  {
833  const cell& cFaces = cells[cellI];
834 
835  label nIntFaces = 0;
836  forAll(cFaces, i)
837  {
838  label bFaceI = cFaces[i]-mesh.nInternalFaces();
839  if (bFaceI < 0)
840  {
841  nIntFaces++;
842  }
843  else
844  {
845  label patchI = pbm.patchID()[bFaceI];
846  if (pbm[patchI].coupled())
847  {
848  nIntFaces++;
849  }
850  }
851  }
852 
853  if (nIntFaces == nFaces)
854  {
855  candidateCellSet.insert(cellI);
856  }
857  }
858 
859  if (debug&meshRefinement::MESH)
860  {
861  Pout<< "Dumping " << candidateCellSet.size()
862  << " cells to cellSet candidateCellSet." << endl;
863  candidateCellSet.instance() = meshRefiner_.timeName();
864  candidateCellSet.write();
865  }
866  candidateCells = candidateCellSet.toc();
867  }
868 
869 
870 
871  labelList cellsToRefine
872  (
873  meshRefiner_.meshCutter().consistentRefinement
874  (
875  candidateCells,
876  true
877  )
878  );
879  Info<< "Determined cells to refine in = "
880  << mesh.time().cpuTimeIncrement() << " s" << endl;
881 
882 
883  label nCellsToRefine = cellsToRefine.size();
884  reduce(nCellsToRefine, sumOp<label>());
885 
886  Info<< "Selected for refinement : " << nCellsToRefine
887  << " cells (out of " << mesh.globalData().nTotalCells()
888  << ')' << endl;
889 
890  // Stop when no cells to refine. After a few iterations check if too
891  // few cells
892  if
893  (
894  nCellsToRefine == 0
895  || (
896  iter >= 1
897  && nCellsToRefine <= refineParams.minRefineCells()
898  )
899  )
900  {
901  Info<< "Stopping refining since too few cells selected."
902  << nl << endl;
903  break;
904  }
905 
906 
907  if (debug)
908  {
909  const_cast<Time&>(mesh.time())++;
910  }
911 
912 
913  if
914  (
916  (
917  (mesh.nCells() >= refineParams.maxLocalCells()),
918  orOp<bool>()
919  )
920  )
921  {
922  meshRefiner_.balanceAndRefine
923  (
924  "coarse cell refinement iteration " + name(iter),
925  decomposer_,
926  distributor_,
927  cellsToRefine,
928  refineParams.maxLoadUnbalance()
929  );
930  }
931  else
932  {
933  meshRefiner_.refineAndBalance
934  (
935  "coarse cell refinement iteration " + name(iter),
936  decomposer_,
937  distributor_,
938  cellsToRefine,
939  refineParams.maxLoadUnbalance()
940  );
941  }
942  }
943  return iter;
944 }
945 
946 
947 // Detect cells with opposing intersected faces of differing refinement
948 // level and refine them.
950 (
951  const refinementParameters& refineParams,
952  const label maxIter
953 )
954 {
955  const fvMesh& mesh = meshRefiner_.mesh();
956 
957  label iter = 0;
958 
959  if (refineParams.interfaceRefine())
960  {
961  for (;iter < maxIter; iter++)
962  {
963  Info<< nl
964  << "Refinement transition refinement iteration " << iter << nl
965  << "--------------------------------------------" << nl
966  << endl;
967 
968  const labelList& surfaceIndex = meshRefiner_.surfaceIndex();
969  const hexRef8& cutter = meshRefiner_.meshCutter();
970  const vectorField& fA = mesh.faceAreas();
971  const labelList& faceOwner = mesh.faceOwner();
972 
973 
974  // Determine cells to refine
975  // ~~~~~~~~~~~~~~~~~~~~~~~~~
976 
977  const cellList& cells = mesh.cells();
978 
979  labelList candidateCells;
980  {
981  // Pass1: pick up cells with differing face level
982 
983  cellSet transitionCells
984  (
985  mesh,
986  "transitionCells",
987  cells.size()/100
988  );
989 
990  forAll(cells, cellI)
991  {
992  const cell& cFaces = cells[cellI];
993  label cLevel = cutter.cellLevel()[cellI];
994 
995  forAll(cFaces, cFaceI)
996  {
997  label faceI = cFaces[cFaceI];
998 
999  if (surfaceIndex[faceI] != -1)
1000  {
1001  label fLevel = cutter.faceLevel(faceI);
1002  if (fLevel != cLevel)
1003  {
1004  transitionCells.insert(cellI);
1005  }
1006  }
1007  }
1008  }
1009 
1010 
1011  cellSet candidateCellSet
1012  (
1013  mesh,
1014  "candidateCells",
1015  cells.size()/1000
1016  );
1017 
1018  // Pass2: check for oppositeness
1019 
1020  //forAllConstIter(cellSet, transitionCells, iter)
1021  //{
1022  // label cellI = iter.key();
1023  // const cell& cFaces = cells[cellI];
1024  // const point& cc = cellCentres[cellI];
1025  // const scalar rCVol = pow(cellVolumes[cellI], -5.0/3.0);
1026  //
1027  // // Determine principal axes of cell
1028  // symmTensor R(symmTensor::zero);
1029  //
1030  // forAll(cFaces, i)
1031  // {
1032  // label faceI = cFaces[i];
1033  //
1034  // const point& fc = faceCentres[faceI];
1035  //
1036  // // Calculate face-pyramid volume
1037  // scalar pyrVol = 1.0/3.0 * fA[faceI] & (fc-cc);
1038  //
1039  // if (faceOwner[faceI] != cellI)
1040  // {
1041  // pyrVol = -pyrVol;
1042  // }
1043  //
1044  // // Calculate face-pyramid centre
1045  // vector pc = (3.0/4.0)*fc + (1.0/4.0)*cc;
1046  //
1047  // R += pyrVol*sqr(pc-cc)*rCVol;
1048  // }
1049  //
1050  // //- MEJ: Problem: truncation errors cause complex evs
1051  // vector lambdas(eigenValues(R));
1052  // const tensor axes(eigenVectors(R, lambdas));
1053  //
1054  //
1055  // // Check if this cell has
1056  // // - opposing sides intersected
1057  // // - which are of different refinement level
1058  // // - plus the inbetween face
1059  //
1060  // labelVector plusFaceLevel(labelVector(-1, -1, -1));
1061  // labelVector minFaceLevel(labelVector(-1, -1, -1));
1062  //
1063  // forAll(cFaces, cFaceI)
1064  // {
1065  // label faceI = cFaces[cFaceI];
1066  //
1067  // if (surfaceIndex[faceI] != -1)
1068  // {
1069  // label fLevel = cutter.faceLevel(faceI);
1070  //
1071  // // Get outwards pointing normal
1072  // vector n = fA[faceI]/mag(fA[faceI]);
1073  // if (faceOwner[faceI] != cellI)
1074  // {
1075  // n = -n;
1076  // }
1077  //
1078  // // What is major direction and sign
1079  // direction cmpt = vector::X;
1080  // scalar maxComp = (n&axes.x());
1081  //
1082  // scalar yComp = (n&axes.y());
1083  // scalar zComp = (n&axes.z());
1084  //
1085  // if (mag(yComp) > mag(maxComp))
1086  // {
1087  // maxComp = yComp;
1088  // cmpt = vector::Y;
1089  // }
1090  //
1091  // if (mag(zComp) > mag(maxComp))
1092  // {
1093  // maxComp = zComp;
1094  // cmpt = vector::Z;
1095  // }
1096  //
1097  // if (maxComp > 0)
1098  // {
1099  // plusFaceLevel[cmpt] = max
1100  // (
1101  // plusFaceLevel[cmpt],
1102  // fLevel
1103  // );
1104  // }
1105  // else
1106  // {
1107  // minFaceLevel[cmpt] = max
1108  // (
1109  // minFaceLevel[cmpt],
1110  // fLevel
1111  // );
1112  // }
1113  // }
1114  // }
1115  //
1116  // // Check if we picked up any opposite differing level
1117  // for (direction dir = 0; dir < vector::nComponents; dir++)
1118  // {
1119  // if
1120  // (
1121  // plusFaceLevel[dir] != -1
1122  // && minFaceLevel[dir] != -1
1123  // && plusFaceLevel[dir] != minFaceLevel[dir]
1124  // )
1125  // {
1126  // candidateCellSet.insert(cellI);
1127  // }
1128  // }
1129  //}
1130 
1131  const scalar oppositeCos = Foam::cos(Foam::degToRad(135));
1132 
1133  forAllConstIter(cellSet, transitionCells, iter)
1134  {
1135  label cellI = iter.key();
1136  const cell& cFaces = cells[cellI];
1137  label cLevel = cutter.cellLevel()[cellI];
1138 
1139  // Detect opposite intersection
1140  bool foundOpposite = false;
1141 
1142  forAll(cFaces, cFaceI)
1143  {
1144  label faceI = cFaces[cFaceI];
1145 
1146  if
1147  (
1148  surfaceIndex[faceI] != -1
1149  && cutter.faceLevel(faceI) > cLevel
1150  )
1151  {
1152  // Get outwards pointing normal
1153  vector n = fA[faceI]/mag(fA[faceI]);
1154  if (faceOwner[faceI] != cellI)
1155  {
1156  n = -n;
1157  }
1158 
1159  // Check for any opposite intersection
1160  forAll(cFaces, cFaceI2)
1161  {
1162  label face2I = cFaces[cFaceI2];
1163 
1164  if
1165  (
1166  face2I != faceI
1167  && surfaceIndex[face2I] != -1
1168  )
1169  {
1170  // Get outwards pointing normal
1171  vector n2 = fA[face2I]/mag(fA[face2I]);
1172  if (faceOwner[face2I] != cellI)
1173  {
1174  n2 = -n2;
1175  }
1176 
1177 
1178  if ((n&n2) < oppositeCos)
1179  {
1180  foundOpposite = true;
1181  break;
1182  }
1183  }
1184  }
1185 
1186  if (foundOpposite)
1187  {
1188  break;
1189  }
1190  }
1191  }
1192 
1193 
1194  if (foundOpposite)
1195  {
1196  candidateCellSet.insert(cellI);
1197  }
1198  }
1199 
1200  if (debug&meshRefinement::MESH)
1201  {
1202  Pout<< "Dumping " << candidateCellSet.size()
1203  << " cells to cellSet candidateCellSet." << endl;
1204  candidateCellSet.instance() = meshRefiner_.timeName();
1205  candidateCellSet.write();
1206  }
1207  candidateCells = candidateCellSet.toc();
1208  }
1209 
1210 
1211 
1212  labelList cellsToRefine
1213  (
1214  meshRefiner_.meshCutter().consistentRefinement
1215  (
1216  candidateCells,
1217  true
1218  )
1219  );
1220  Info<< "Determined cells to refine in = "
1221  << mesh.time().cpuTimeIncrement() << " s" << endl;
1222 
1223 
1224  label nCellsToRefine = cellsToRefine.size();
1225  reduce(nCellsToRefine, sumOp<label>());
1226 
1227  Info<< "Selected for refinement : " << nCellsToRefine
1228  << " cells (out of " << mesh.globalData().nTotalCells()
1229  << ')' << endl;
1230 
1231  // Stop when no cells to refine. After a few iterations check if too
1232  // few cells
1233  if
1234  (
1235  nCellsToRefine == 0
1236  || (
1237  iter >= 1
1238  && nCellsToRefine <= refineParams.minRefineCells()
1239  )
1240  )
1241  {
1242  Info<< "Stopping refining since too few cells selected."
1243  << nl << endl;
1244  break;
1245  }
1246 
1247 
1248  if (debug)
1249  {
1250  const_cast<Time&>(mesh.time())++;
1251  }
1252 
1253 
1254  if
1255  (
1256  returnReduce
1257  (
1258  (mesh.nCells() >= refineParams.maxLocalCells()),
1259  orOp<bool>()
1260  )
1261  )
1262  {
1263  meshRefiner_.balanceAndRefine
1264  (
1265  "interface cell refinement iteration " + name(iter),
1266  decomposer_,
1267  distributor_,
1268  cellsToRefine,
1269  refineParams.maxLoadUnbalance()
1270  );
1271  }
1272  else
1273  {
1274  meshRefiner_.refineAndBalance
1275  (
1276  "interface cell refinement iteration " + name(iter),
1277  decomposer_,
1278  distributor_,
1279  cellsToRefine,
1280  refineParams.maxLoadUnbalance()
1281  );
1282  }
1283  }
1284  }
1285  return iter;
1286 }
1287 
1288 
1291  const refinementParameters& refineParams,
1292  const label nBufferLayers
1293 )
1294 {
1295  Info<< nl
1296  << "Removing mesh beyond surface intersections" << nl
1297  << "------------------------------------------" << nl
1298  << endl;
1299 
1300  const fvMesh& mesh = meshRefiner_.mesh();
1301 
1302  if (debug)
1303  {
1304  const_cast<Time&>(mesh.time())++;
1305  }
1306 
1307  meshRefiner_.splitMesh
1308  (
1309  nBufferLayers, // nBufferLayers
1310  globalToMasterPatch_,
1311  globalToSlavePatch_,
1312  refineParams.locationsInMesh(),
1313  refineParams.zonesInMesh(),
1314  refineParams.locationsOutsideMesh()
1315  );
1316 
1317  if (debug&meshRefinement::MESH)
1318  {
1319  Pout<< "Writing subsetted mesh to time "
1320  << meshRefiner_.timeName() << endl;
1321  meshRefiner_.write
1322  (
1325  (
1326  meshRefinement::writeLevel()
1327  | meshRefinement::WRITEMESH
1328  ),
1329  mesh.time().path()/meshRefiner_.timeName()
1330  );
1331  Pout<< "Dumped mesh in = "
1332  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
1333  }
1334 }
1335 
1336 
1339  const refinementParameters& refineParams,
1340  const label maxIter
1341 )
1342 {
1343  const fvMesh& mesh = meshRefiner_.mesh();
1344 
1345  // Mark current boundary faces with 0. Have meshRefiner maintain them.
1346  meshRefiner_.userFaceData().setSize(1);
1347 
1348  // mark list to remove any refined faces
1349  meshRefiner_.userFaceData()[0].first() = meshRefinement::REMOVE;
1350  meshRefiner_.userFaceData()[0].second() = createWithValues<labelList>
1351  (
1352  mesh.nFaces(),
1353  -1,
1354  meshRefiner_.intersectedFaces(),
1355  0
1356  );
1357 
1358  // Determine the maximum refinement level over all volume refinement
1359  // regions. This determines the minumum number of shell refinement
1360  // iterations.
1361  label overallMaxShellLevel = meshRefiner_.shells().maxLevel();
1362 
1363  label iter;
1364  for (iter = 0; iter < maxIter; iter++)
1365  {
1366  Info<< nl
1367  << "Shell refinement iteration " << iter << nl
1368  << "----------------------------" << nl
1369  << endl;
1370 
1371  labelList candidateCells
1372  (
1373  meshRefiner_.refineCandidates
1374  (
1375  refineParams.locationsInMesh(),
1376  refineParams.curvature(),
1377  refineParams.planarAngle(),
1378 
1379  false, // featureRefinement
1380  true, // featureDistanceRefinement
1381  true, // internalRefinement
1382  false, // surfaceRefinement
1383  false, // curvatureRefinement
1384  false, // smallFeatureRefinement
1385  false, // gapRefinement
1386  false, // bigGapRefinement
1387  false, // spreadGapSize
1388  refineParams.maxGlobalCells(),
1389  refineParams.maxLocalCells()
1390  )
1391  );
1392 
1393  if (debug&meshRefinement::MESH)
1394  {
1395  Pout<< "Dumping " << candidateCells.size()
1396  << " cells to cellSet candidateCellsFromShells." << endl;
1397 
1398  cellSet c(mesh, "candidateCellsFromShells", candidateCells);
1399  c.instance() = meshRefiner_.timeName();
1400  c.write();
1401  }
1402 
1403  // Problem choosing starting faces for bufferlayers (bFaces)
1404  // - we can't use the current intersected boundary faces
1405  // (intersectedFaces) since this grows indefinitely
1406  // - if we use 0 faces we don't satisfy bufferLayers from the
1407  // surface.
1408  // - possibly we want to have bFaces only the initial set of faces
1409  // and maintain the list while doing the refinement.
1410  labelList bFaces
1411  (
1412  findIndices(meshRefiner_.userFaceData()[0].second(), 0)
1413  );
1414 
1415  //Info<< "Collected boundary faces : "
1416  // << returnReduce(bFaces.size(), sumOp<label>()) << endl;
1417 
1418  labelList cellsToRefine;
1419 
1420  if (refineParams.nBufferLayers() <= 2)
1421  {
1422  cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement
1423  (
1424  refineParams.nBufferLayers(),
1425  candidateCells, // cells to refine
1426  bFaces, // faces for nBufferLayers
1427  1, // point difference
1428  meshRefiner_.intersectedPoints() // points to check
1429  );
1430  }
1431  else
1432  {
1433  cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement2
1434  (
1435  refineParams.nBufferLayers(),
1436  candidateCells, // cells to refine
1437  bFaces // faces for nBufferLayers
1438  );
1439  }
1440 
1441  Info<< "Determined cells to refine in = "
1442  << mesh.time().cpuTimeIncrement() << " s" << endl;
1443 
1444 
1445  label nCellsToRefine = cellsToRefine.size();
1446  reduce(nCellsToRefine, sumOp<label>());
1447 
1448  Info<< "Selected for internal refinement : " << nCellsToRefine
1449  << " cells (out of " << mesh.globalData().nTotalCells()
1450  << ')' << endl;
1451 
1452  // Stop when no cells to refine or have done minimum necessary
1453  // iterations and not enough cells to refine.
1454  if
1455  (
1456  nCellsToRefine == 0
1457  || (
1458  iter >= overallMaxShellLevel
1459  && nCellsToRefine <= refineParams.minRefineCells()
1460  )
1461  )
1462  {
1463  Info<< "Stopping refining since too few cells selected."
1464  << nl << endl;
1465  break;
1466  }
1467 
1468 
1469  if (debug)
1470  {
1471  const_cast<Time&>(mesh.time())++;
1472  }
1473 
1474  if
1475  (
1476  returnReduce
1477  (
1478  (mesh.nCells() >= refineParams.maxLocalCells()),
1479  orOp<bool>()
1480  )
1481  )
1482  {
1483  meshRefiner_.balanceAndRefine
1484  (
1485  "shell refinement iteration " + name(iter),
1486  decomposer_,
1487  distributor_,
1488  cellsToRefine,
1489  refineParams.maxLoadUnbalance()
1490  );
1491  }
1492  else
1493  {
1494  meshRefiner_.refineAndBalance
1495  (
1496  "shell refinement iteration " + name(iter),
1497  decomposer_,
1498  distributor_,
1499  cellsToRefine,
1500  refineParams.maxLoadUnbalance()
1501  );
1502  }
1503  }
1504  meshRefiner_.userFaceData().clear();
1505 
1506  return iter;
1507 }
1508 
1509 
1512  const refinementParameters& refineParams,
1513  const snapParameters& snapParams,
1514  const bool handleSnapProblems,
1515  const dictionary& motionDict
1516 )
1517 {
1518  Info<< nl
1519  << "Splitting mesh at surface intersections" << nl
1520  << "---------------------------------------" << nl
1521  << endl;
1522 
1523  const fvMesh& mesh = meshRefiner_.mesh();
1524 
1525  if (debug)
1526  {
1527  const_cast<Time&>(mesh.time())++;
1528  }
1529 
1530  // Introduce baffles at surface intersections. Note:
1531  // meshRefiment::surfaceIndex() will
1532  // be like boundary face from now on so not coupled anymore.
1533  meshRefiner_.baffleAndSplitMesh
1534  (
1535  handleSnapProblems, // detect&remove potential snap problem
1536 
1537  // Snap problem cell detection
1538  snapParams,
1539  refineParams.useTopologicalSnapDetection(),
1540  false, // perpendicular edge connected cells
1541  scalarField(0), // per region perpendicular angle
1542 
1543  motionDict,
1544  const_cast<Time&>(mesh.time()),
1545  globalToMasterPatch_,
1546  globalToSlavePatch_,
1547  refineParams.locationsInMesh(),
1548  refineParams.zonesInMesh(),
1549  refineParams.locationsOutsideMesh()
1550  );
1551 
1552 
1553  if (!handleSnapProblems) // merge free standing baffles?
1554  {
1555  meshRefiner_.mergeFreeStandingBaffles
1556  (
1557  snapParams,
1558  refineParams.useTopologicalSnapDetection(),
1559  false, // perpendicular edge connected cells
1560  scalarField(0), // per region perpendicular angle
1561  refineParams.planarAngle(),
1562  motionDict,
1563  const_cast<Time&>(mesh.time()),
1564  globalToMasterPatch_,
1565  globalToSlavePatch_,
1566  refineParams.locationsInMesh(),
1567  refineParams.locationsOutsideMesh()
1568  );
1569  }
1570 }
1571 
1572 
1575  const refinementParameters& refineParams,
1576  wordPairHashTable& zonesToFaceZone
1577 )
1578 {
1579  // Mesh is at its finest. Do zoning
1580  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1581  // This puts all faces with intersection across a zoneable surface
1582  // into that surface's faceZone. All cells inside faceZone get given the
1583  // same cellZone.
1584 
1585  const labelList namedSurfaces =
1586  surfaceZonesInfo::getNamedSurfaces(meshRefiner_.surfaces().surfZones());
1587 
1588  if
1589  (
1590  namedSurfaces.size()
1591  || refineParams.zonesInMesh().size()
1592  )
1593  {
1594  Info<< nl
1595  << "Introducing zones for interfaces" << nl
1596  << "--------------------------------" << nl
1597  << endl;
1598 
1599  const fvMesh& mesh = meshRefiner_.mesh();
1600 
1601  if (debug)
1602  {
1603  const_cast<Time&>(mesh.time())++;
1604  }
1605 
1606  meshRefiner_.zonify
1607  (
1608  refineParams.allowFreeStandingZoneFaces(),
1609  refineParams.locationsInMesh(),
1610  refineParams.zonesInMesh(),
1611  zonesToFaceZone
1612  );
1613 
1614  if (debug&meshRefinement::MESH)
1615  {
1616  Pout<< "Writing zoned mesh to time "
1617  << meshRefiner_.timeName() << endl;
1618  meshRefiner_.write
1619  (
1622  (
1623  meshRefinement::writeLevel()
1624  | meshRefinement::WRITEMESH
1625  ),
1626  mesh.time().path()/meshRefiner_.timeName()
1627  );
1628  }
1629 
1630  // Check that all faces are synced
1631  meshRefinement::checkCoupledFaceZones(mesh);
1632  }
1633 }
1634 
1635 
1638  const refinementParameters& refineParams,
1639  const snapParameters& snapParams,
1640  const bool handleSnapProblems,
1641  const dictionary& motionDict
1642 )
1643 {
1644  Info<< nl
1645  << "Handling cells with snap problems" << nl
1646  << "---------------------------------" << nl
1647  << endl;
1648 
1649  const fvMesh& mesh = meshRefiner_.mesh();
1650 
1651  // Introduce baffles and split mesh
1652  if (debug)
1653  {
1654  const_cast<Time&>(mesh.time())++;
1655  }
1656 
1657  const scalarField& perpAngle = meshRefiner_.surfaces().perpendicularAngle();
1658 
1659  meshRefiner_.baffleAndSplitMesh
1660  (
1661  handleSnapProblems,
1662 
1663  // Snap problem cell detection
1664  snapParams,
1665  refineParams.useTopologicalSnapDetection(),
1666  handleSnapProblems, // remove perp edge connected cells
1667  perpAngle, // perp angle
1668 
1669  motionDict,
1670  const_cast<Time&>(mesh.time()),
1671  globalToMasterPatch_,
1672  globalToSlavePatch_,
1673  refineParams.locationsInMesh(),
1674  refineParams.zonesInMesh(),
1675  refineParams.locationsOutsideMesh()
1676  );
1677 
1678  // Merge free-standing baffles always
1679  meshRefiner_.mergeFreeStandingBaffles
1680  (
1681  snapParams,
1682  refineParams.useTopologicalSnapDetection(),
1683  handleSnapProblems,
1684  perpAngle,
1685  refineParams.planarAngle(),
1686  motionDict,
1687  const_cast<Time&>(mesh.time()),
1688  globalToMasterPatch_,
1689  globalToSlavePatch_,
1690  refineParams.locationsInMesh(),
1691  refineParams.locationsOutsideMesh()
1692  );
1693 
1694  if (debug)
1695  {
1696  const_cast<Time&>(mesh.time())++;
1697  }
1698 
1699  // Duplicate points on baffles that are on more than one cell
1700  // region. This will help snapping pull them to separate surfaces.
1701  meshRefiner_.dupNonManifoldPoints();
1702 
1703 
1704  // Merge all baffles that are still remaining after duplicating points.
1705  List<labelPair> couples(localPointRegion::findDuplicateFacePairs(mesh));
1706 
1707  label nCouples = returnReduce(couples.size(), sumOp<label>());
1708 
1709  Info<< "Detected unsplittable baffles : " << nCouples << endl;
1710 
1711  if (nCouples > 0)
1712  {
1713  // Actually merge baffles. Note: not exactly parallellized. Should
1714  // convert baffle faces into processor faces if they resulted
1715  // from them.
1716  meshRefiner_.mergeBaffles(couples, Map<label>(0));
1717 
1718  if (debug)
1719  {
1720  // Debug:test all is still synced across proc patches
1721  meshRefiner_.checkData();
1722  }
1723 
1724  // Remove any now dangling parts
1725  meshRefiner_.splitMeshRegions
1726  (
1727  globalToMasterPatch_,
1728  globalToSlavePatch_,
1729  refineParams.locationsInMesh(),
1730  refineParams.locationsOutsideMesh()
1731  );
1732 
1733  if (debug)
1734  {
1735  // Debug:test all is still synced across proc patches
1736  meshRefiner_.checkData();
1737  }
1738 
1739  Info<< "Merged free-standing baffles in = "
1740  << mesh.time().cpuTimeIncrement() << " s." << endl;
1741  }
1742 
1743  if (debug&meshRefinement::MESH)
1744  {
1745  Pout<< "Writing handleProblemCells mesh to time "
1746  << meshRefiner_.timeName() << endl;
1747  meshRefiner_.write
1748  (
1751  (
1752  meshRefinement::writeLevel()
1753  | meshRefinement::WRITEMESH
1754  ),
1755  mesh.time().path()/meshRefiner_.timeName()
1756  );
1757  }
1758 }
1759 
1760 
1763  meshRefinement& meshRefiner,
1764  const refinementParameters& refineParams,
1765  const HashTable<Pair<word> >& faceZoneToPatches
1766 )
1767 {
1768  if (faceZoneToPatches.size())
1769  {
1770  Info<< nl
1771  << "Adding patches for face zones" << nl
1772  << "-----------------------------" << nl
1773  << endl;
1774 
1775  Info<< setf(ios_base::left)
1776  << setw(6) << "Patch"
1777  << setw(20) << "Type"
1778  << setw(30) << "Name"
1779  << setw(30) << "FaceZone"
1780  << setw(10) << "FaceType"
1781  << nl
1782  << setw(6) << "-----"
1783  << setw(20) << "----"
1784  << setw(30) << "----"
1785  << setw(30) << "--------"
1786  << setw(10) << "--------"
1787  << endl;
1788 
1789  const polyMesh& mesh = meshRefiner.mesh();
1790 
1791  // Add patches for added inter-region faceZones
1792  forAllConstIter(HashTable<Pair<word> >, faceZoneToPatches, iter)
1793  {
1794  const word& fzName = iter.key();
1795  const Pair<word>& patchNames = iter();
1796 
1797  // Get any user-defined faceZone data
1799  dictionary patchInfo = refineParams.getZoneInfo(fzName, fzType);
1800 
1801  const word& masterName = fzName;
1802  //const word slaveName = fzName + "_slave";
1803  //const word slaveName = czNames.second()+"_to_"+czNames.first();
1804  const word& slaveName = patchNames.second();
1805 
1806  label mpI = meshRefiner.addMeshedPatch(masterName, patchInfo);
1807 
1808  Info<< setf(ios_base::left)
1809  << setw(6) << mpI
1810  << setw(20) << mesh.boundaryMesh()[mpI].type()
1811  << setw(30) << masterName
1812  << setw(30) << fzName
1813  << setw(10) << surfaceZonesInfo::faceZoneTypeNames[fzType]
1814  << nl;
1815 
1816 
1817  label slI = meshRefiner.addMeshedPatch(slaveName, patchInfo);
1818 
1819  Info<< setf(ios_base::left)
1820  << setw(6) << slI
1821  << setw(20) << mesh.boundaryMesh()[slI].type()
1822  << setw(30) << slaveName
1823  << setw(30) << fzName
1824  << setw(10) << surfaceZonesInfo::faceZoneTypeNames[fzType]
1825  << nl;
1826 
1827  meshRefiner.addFaceZone(fzName, masterName, slaveName, fzType);
1828  }
1829 
1830  Info<< endl;
1831  }
1832 }
1833 
1834 
1837  const bool geometricMerge,
1838  const refinementParameters& refineParams,
1839  const dictionary& motionDict
1840 )
1841 {
1842  Info<< nl
1843  << "Merge refined boundary faces" << nl
1844  << "----------------------------" << nl
1845  << endl;
1846 
1847  const fvMesh& mesh = meshRefiner_.mesh();
1848 
1849  if (geometricMerge)
1850  {
1851  meshRefiner_.mergePatchFacesUndo
1852  (
1853  Foam::cos(degToRad(45.0)),
1854  Foam::cos(degToRad(45.0)),
1855  meshRefiner_.meshedPatches(),
1856  motionDict,
1857  labelList(mesh.nFaces(), -1)
1858  );
1859  }
1860  else
1861  {
1862  // Still merge refined boundary faces if all four are on same patch
1863  meshRefiner_.mergePatchFaces
1864  (
1865  Foam::cos(degToRad(45.0)),
1866  Foam::cos(degToRad(45.0)),
1867  4, // only merge faces split into 4
1868  meshRefiner_.meshedPatches()
1869  );
1870  }
1871 
1872  if (debug)
1873  {
1874  meshRefiner_.checkData();
1875  }
1876 
1877  meshRefiner_.mergeEdgesUndo(Foam::cos(degToRad(45.0)), motionDict);
1878 
1879  if (debug)
1880  {
1881  meshRefiner_.checkData();
1882  }
1883 }
1884 
1885 
1888  const dictionary& refineDict,
1889  const refinementParameters& refineParams,
1890  const snapParameters& snapParams,
1891  const bool prepareForSnapping,
1892  const bool doMergePatchFaces,
1893  const dictionary& motionDict
1894 )
1895 {
1896  Info<< nl
1897  << "Refinement phase" << nl
1898  << "----------------" << nl
1899  << endl;
1900 
1901  const fvMesh& mesh = meshRefiner_.mesh();
1902 
1903  // Check that all the keep points are inside the mesh.
1904  refineParams.findCells(true, mesh, refineParams.locationsInMesh());
1905 
1906  // Refine around feature edges
1907  featureEdgeRefine
1908  (
1909  refineParams,
1910  100, // maxIter
1911  0 // min cells to refine
1912  );
1913 
1914  // Refine cells that contain a gap
1915  smallFeatureRefine
1916  (
1917  refineParams,
1918  100 // maxIter
1919  );
1920 
1921  // Refine based on surface
1922  surfaceOnlyRefine
1923  (
1924  refineParams,
1925  100 // maxIter
1926  );
1927 
1928  gapOnlyRefine
1929  (
1930  refineParams,
1931  100 // maxIter
1932  );
1933 
1934  // Remove cells (a certain distance) beyond surface intersections
1935  removeInsideCells
1936  (
1937  refineParams,
1938  1 // nBufferLayers
1939  );
1940 
1941  // Refine consistently across narrow gaps (a form of shell refinement)
1942  bigGapOnlyRefine
1943  (
1944  refineParams,
1945  true, // spreadGapSize
1946  100 // maxIter
1947  );
1948 
1949  // Internal mesh refinement
1950  shellRefine
1951  (
1952  refineParams,
1953  100 // maxIter
1954  );
1955 
1956  // Refine any hexes with 5 or 6 faces refined to make smooth edges
1957  danglingCellRefine
1958  (
1959  refineParams,
1960  21, // 1 coarse face + 5 refined faces
1961  100 // maxIter
1962  );
1963  danglingCellRefine
1964  (
1965  refineParams,
1966  24, // 0 coarse faces + 6 refined faces
1967  100 // maxIter
1968  );
1969 
1970  // Refine any cells with differing refinement level on either side
1971  refinementInterfaceRefine
1972  (
1973  refineParams,
1974  10 // maxIter
1975  );
1976 
1977  // Introduce baffles at surface intersections. Remove sections unreachable
1978  // from keepPoint.
1979  baffleAndSplitMesh
1980  (
1981  refineParams,
1982  snapParams,
1983  prepareForSnapping,
1984  motionDict
1985  );
1986 
1987  // Mesh is at its finest. Do optional zoning (cellZones and faceZones)
1988  wordPairHashTable zonesToFaceZone;
1989  zonify(refineParams, zonesToFaceZone);
1990 
1991  // Create pairs of patches for faceZones
1992  {
1993  HashTable<Pair<word> > faceZoneToPatches(zonesToFaceZone.size());
1994 
1995  // Note: zonesToFaceZone contains the same data on different
1996  // processors but in different order. We could sort the
1997  // contents but instead just loop in sortedToc order.
1998  List<Pair<word> > czs(zonesToFaceZone.sortedToc());
1999 
2000  forAll(czs, i)
2001  {
2002  const Pair<word>& czNames = czs[i];
2003  const word& fzName = zonesToFaceZone[czNames];
2004 
2005  const word& masterName = fzName;
2006  const word slaveName = czNames.second() + "_to_" + czNames.first();
2007  Pair<word> patches(masterName, slaveName);
2008  faceZoneToPatches.insert(fzName, patches);
2009  }
2010  addFaceZones(meshRefiner_, refineParams, faceZoneToPatches);
2011  }
2012 
2013  // Pull baffles apart
2014  splitAndMergeBaffles
2015  (
2016  refineParams,
2017  snapParams,
2018  prepareForSnapping,
2019  motionDict
2020  );
2021 
2022  // Do something about cells with refined faces on the boundary
2023  if (prepareForSnapping)
2024  {
2025  mergePatchFaces(doMergePatchFaces, refineParams, motionDict);
2026  }
2027 
2028 
2029  if (Pstream::parRun())
2030  {
2031  Info<< nl
2032  << "Doing final balancing" << nl
2033  << "---------------------" << nl
2034  << endl;
2035 
2036  // Do final balancing. Keep zoned faces on one processor since the
2037  // snap phase will convert them to baffles and this only works for
2038  // internal faces.
2039  meshRefiner_.balance
2040  (
2041  true, // keepZoneFaces
2042  false, // keepBaffles
2043  scalarField(mesh.nCells(), 1), // cellWeights
2044  decomposer_,
2045  distributor_
2046  );
2047  }
2048 }
2049 
2050 
2051 // ************************************************************************* //
Foam::refinementParameters::allowFreeStandingZoneFaces
bool allowFreeStandingZoneFaces() const
Are zone faces allowed only inbetween different cell zones.
Definition: refinementParameters.H:185
shellSurfaces.H
Foam::refinementParameters::zonesInMesh
const wordList & zonesInMesh() const
Per area the zone name.
Definition: refinementParameters.H:172
Foam::setf
Smanip< ios_base::fmtflags > setf(const ios_base::fmtflags flags)
Definition: IOmanip.H:164
Foam::refinementParameters::useTopologicalSnapDetection
bool useTopologicalSnapDetection() const
Use old topology based problem-cell removal.
Definition: refinementParameters.H:192
Foam::refinementParameters::maxGlobalCells
label maxGlobalCells() const
Total number of cells.
Definition: refinementParameters.H:130
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
Foam::refinementParameters::maxLoadUnbalance
scalar maxLoadUnbalance() const
Allowed load unbalance.
Definition: refinementParameters.H:198
Foam::surfaceZonesInfo::faceZoneType
faceZoneType
What to do with faceZone faces.
Definition: surfaceZonesInfo.H:73
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
Foam::autoRefineDriver::addFaceZones
static void addFaceZones(meshRefinement &meshRefiner, const refinementParameters &refineParams, const HashTable< Pair< word > > &faceZoneToPatches)
Helper: add faceZones and patches.
Definition: autoRefineDriver.C:1762
Foam::hexRef8::cellLevel
const labelIOList & cellLevel() const
Definition: hexRef4.H:389
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
Foam::polyBoundaryMesh
Foam::polyBoundaryMesh.
Definition: polyBoundaryMesh.H:60
Foam::HashTable::toc
List< Key > toc() const
Return the table of contents.
Definition: HashTable.C:201
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::refinementParameters::planarAngle
scalar planarAngle() const
Angle when two intersections are considered to be planar.
Definition: refinementParameters.H:154
Foam::autoRefineDriver::baffleAndSplitMesh
void baffleAndSplitMesh(const refinementParameters &refineParams, const snapParameters &snapParams, const bool handleSnapProblems, const dictionary &motionDict)
Add baffles and remove unreachable cells.
Definition: autoRefineDriver.C:1511
labelVector.H
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:2145
Foam::autoRefineDriver::removeInsideCells
void removeInsideCells(const refinementParameters &refineParams, const label nBufferLayers)
Remove all cells within intersected region.
Definition: autoRefineDriver.C:1290
localPointRegion.H
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Foam::Pair::first
const Type & first() const
Return first.
Definition: Pair.H:87
Foam::HashTable::insert
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
Foam::Map< label >
unitConversion.H
Unit conversion functions.
Foam::regIOobject::write
virtual bool write() const
Write using setting from DB.
Definition: regIOobjectWrite.C:126
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:174
Foam::autoRefineDriver::splitAndMergeBaffles
void splitAndMergeBaffles(const refinementParameters &refineParams, const snapParameters &snapParams, const bool handleSnapProblems, const dictionary &motionDict)
Definition: autoRefineDriver.C:1637
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
refinementFeatures.H
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::autoRefineDriver::refinementInterfaceRefine
label refinementInterfaceRefine(const refinementParameters &refineParams, const label maxIter)
Refine cells with opposite faces with differing refinement level.
Definition: autoRefineDriver.C:950
Foam::IOobject::instance
const fileName & instance() const
Definition: IOobject.H:350
Foam::meshRefinement::mesh
const fvMesh & mesh() const
Reference to mesh.
Definition: meshRefinement.H:817
syncTools.H
Foam::help::mergePatchFaces
faceList mergePatchFaces(const List< DynList< label > > &pfcs, const pointField &polyPoints)
Definition: helperFunctionsGeometryQueriesI.H:232
Foam::autoRefineDriver::bigGapOnlyRefine
label bigGapOnlyRefine(const refinementParameters &refineParams, const bool spreadGapSize, const label maxIter)
Refine all cells in large gaps.
Definition: autoRefineDriver.C:662
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
Foam::autoRefineDriver::zonify
void zonify(const refinementParameters &refineParams, wordPairHashTable &zonesToFaceZone)
Add zones.
Definition: autoRefineDriver.C:1574
Foam::autoRefineDriver::featureEdgeRefine
label featureEdgeRefine(const refinementParameters &refineParams, const label maxIter, const label minRefine)
Refine all cells pierced by explicit feature edges.
Definition: autoRefineDriver.C:76
mapDistributePolyMesh.H
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::autoRefineDriver::gapOnlyRefine
label gapOnlyRefine(const refinementParameters &refineParams, const label maxIter)
Refine all cells in small gaps.
Definition: autoRefineDriver.C:431
Foam::polyBoundaryMesh::patchID
const labelList & patchID() const
Per boundary face label the patch index.
Definition: polyBoundaryMesh.C:399
Foam::snapParameters
Simple container to keep together snap specific information.
Definition: snapParameters.H:50
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::refinementParameters::maxLocalCells
label maxLocalCells() const
Per processor max number of cells.
Definition: refinementParameters.H:136
Foam::refinementParameters::nBufferLayers
label nBufferLayers() const
Number of layers between different refinement levels.
Definition: refinementParameters.H:160
Foam::orOp
Definition: ops.H:178
Foam::Ostream::write
virtual Ostream & write(const token &)=0
Write next token to stream.
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::autoRefineDriver::mergePatchFaces
void mergePatchFaces(const bool geometricMerge, const refinementParameters &refineParams, const dictionary &motionDict)
Merge refined boundary faces (from exposing coarser cell)
Definition: autoRefineDriver.C:1836
refinementSurfaces.H
MESH
@ MESH
Definition: extrudeMesh.C:60
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::refinementParameters
Simple container to keep together refinement specific information.
Definition: refinementParameters.H:55
Foam::Pair::second
const Type & second() const
Return second.
Definition: Pair.H:99
Foam::refinementParameters::curvature
scalar curvature() const
Curvature.
Definition: refinementParameters.H:148
patchNames
wordList patchNames(nPatches)
Foam::dictionary
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:137
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
meshRefinement.H
Foam::decompositionMethod
Abstract base class for decomposition.
Definition: decompositionMethod.H:48
Foam::refinementParameters::locationsOutsideMesh
const pointField & locationsOutsideMesh() const
Optional points which are checked to be outside the mesh.
Definition: refinementParameters.H:178
Foam::refinementParameters::interfaceRefine
bool interfaceRefine() const
Refine cell with opposite faces with different refinement level.
Definition: refinementParameters.H:209
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::setw
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Foam::cellSet
A collection of cell labels.
Definition: cellSet.H:48
Foam::HashTable::sortedToc
List< Key > sortedToc() const
Return the table of contents as a sorted list.
Definition: HashTable.C:216
Foam::hexRef8::faceLevel
label faceLevel(const label faceI) const
Gets level such that the face has four points <= level.
Definition: hexRef4.C:796
Foam::autoRefineDriver::danglingCellRefine
label danglingCellRefine(const refinementParameters &refineParams, const label nFaces, const label maxIter)
Refine cells with almost all sides refined.
Definition: autoRefineDriver.C:804
Foam::autoRefineDriver::autoRefineDriver
autoRefineDriver(const autoRefineDriver &)
Disallow default bitwise copy construct.
Foam::HashTable
An STL-conforming hash table.
Definition: HashTable.H:61
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::autoRefineDriver::smallFeatureRefine
label smallFeatureRefine(const refinementParameters &refineParams, const label maxIter)
Refine all cells containing small surface features.
Definition: autoRefineDriver.C:186
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::sumOp
Definition: ops.H:162
Foam::Pair< word >
Foam::hexRef8
Refinement of (split) hexes using polyTopoChange.
Definition: hexRef4.H:64
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::HashTable::clear
void clear()
Clear all entries from table.
Definition: HashTable.C:473
refinementParameters.H
Foam::autoRefineDriver::surfaceOnlyRefine
label surfaceOnlyRefine(const refinementParameters &refineParams, const label maxIter)
Refine all cells interacting with the surface.
Definition: autoRefineDriver.C:308
Foam::Vector< scalar >
Foam::meshRefinement::writeType
writeType
Definition: meshRefinement.H:130
Foam::refinementParameters::getZoneInfo
dictionary getZoneInfo(const word &fzName, surfaceZonesInfo::faceZoneType &faceType) const
Get patchInfo and faceType for faceZone.
Definition: refinementParameters.C:123
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
scalarField
volScalarField scalarField(fieldObject, mesh)
Foam::autoRefineDriver::doRefine
void doRefine(const dictionary &refineDict, const refinementParameters &refineParams, const snapParameters &snapParams, const bool prepareForSnapping, const bool mergePatchFaces, const dictionary &motionDict)
Do all the refinement.
Definition: autoRefineDriver.C:1887
Foam::meshRefinement
Helper class which maintains intersections of (changing) mesh with (static) surfaces.
Definition: meshRefinement.H:82
Foam::autoRefineDriver::shellRefine
label shellRefine(const refinementParameters &refineParams, const label maxIter)
Remove all cells inside/outside shell.
Definition: autoRefineDriver.C:1338
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
Foam::meshRefinement::addMeshedPatch
label addMeshedPatch(const word &name, const dictionary &)
Add patch originating from meshing. Update meshedPatches_.
Definition: meshRefinement.C:2068
snapParameters.H
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
patches
patches[0]
Definition: createSingleCellMesh.H:36
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
cellSet.H
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
autoRefineDriver.H
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::findIndices
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurences of given element. Linear search.
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
Foam::fvMeshDistribute
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
Definition: fvMeshDistribute.H:70
Foam::refinementParameters::locationsInMesh
const pointField & locationsInMesh() const
Areas to keep.
Definition: refinementParameters.H:166
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Foam::refinementParameters::minRefineCells
label minRefineCells() const
When to stop refining.
Definition: refinementParameters.H:142
Foam::degToRad
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
Definition: unitConversion.H:45
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:256
Foam::meshRefinement::debugType
debugType
Definition: meshRefinement.H:100