snappyRefineMesh.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-2016 OpenFOAM Foundation
9  Copyright (C) 2018-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 Application
28  snappyRefineMesh
29 
30 Group
31  grpMeshAdvancedUtilities
32 
33 Description
34  Refine cells near to a surface.
35 
36 \*---------------------------------------------------------------------------*/
37 
38 #include "argList.H"
39 #include "Time.H"
40 #include "polyMesh.H"
41 #include "twoDPointCorrector.H"
42 #include "OFstream.H"
43 #include "multiDirRefinement.H"
44 
45 #include "triSurface.H"
46 #include "triSurfaceSearch.H"
47 
48 #include "cellSet.H"
49 #include "pointSet.H"
50 #include "surfaceToCell.H"
51 #include "surfaceToPoint.H"
52 #include "cellToPoint.H"
53 #include "pointToCell.H"
54 #include "cellToCell.H"
55 #include "surfaceSets.H"
56 #include "polyTopoChange.H"
57 #include "polyTopoChanger.H"
58 #include "mapPolyMesh.H"
59 #include "labelIOList.H"
60 #include "emptyPolyPatch.H"
61 #include "removeCells.H"
62 #include "meshSearch.H"
63 
64 using namespace Foam;
65 
66 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
67 
68 
69 // Max cos angle for edges to be considered aligned with axis.
70 static const scalar edgeTol = 1e-3;
71 
72 
73 void writeSet(const cellSet& cells, const string& msg)
74 {
75  Info<< "Writing " << msg << " (" << cells.size() << ") to cellSet "
76  << cells.instance()/cells.local()/cells.name()
77  << endl;
78  cells.write();
79 }
80 
81 
82 direction getNormalDir(const twoDPointCorrector* correct2DPtr)
83 {
84  direction dir = 3;
85 
86  if (correct2DPtr)
87  {
88  const vector& normal = correct2DPtr->planeNormal();
89 
90  if (mag(normal & vector(1, 0, 0)) > 1-edgeTol)
91  {
92  dir = 0;
93  }
94  else if (mag(normal & vector(0, 1, 0)) > 1-edgeTol)
95  {
96  dir = 1;
97  }
98  else if (mag(normal & vector(0, 0, 1)) > 1-edgeTol)
99  {
100  dir = 2;
101  }
102  }
103  return dir;
104 }
105 
106 
107 
108 // Calculate some edge statistics on mesh. Return min. edge length over all
109 // directions but exclude component (0=x, 1=y, 2=z, other=none)
110 scalar getEdgeStats(const primitiveMesh& mesh, const direction excludeCmpt)
111 {
112  label nX = 0;
113  label nY = 0;
114  label nZ = 0;
115 
116  scalar minX = GREAT;
117  scalar maxX = -GREAT;
118  vector x(1, 0, 0);
119 
120  scalar minY = GREAT;
121  scalar maxY = -GREAT;
122  vector y(0, 1, 0);
123 
124  scalar minZ = GREAT;
125  scalar maxZ = -GREAT;
126  vector z(0, 0, 1);
127 
128  scalar minOther = GREAT;
129  scalar maxOther = -GREAT;
130 
131  const edgeList& edges = mesh.edges();
132 
133  forAll(edges, edgei)
134  {
135  const edge& e = edges[edgei];
136 
137  vector eVec(e.vec(mesh.points()));
138 
139  scalar eMag = mag(eVec);
140 
141  eVec /= eMag;
142 
143  if (mag(eVec & x) > 1-edgeTol)
144  {
145  minX = min(minX, eMag);
146  maxX = max(maxX, eMag);
147  nX++;
148  }
149  else if (mag(eVec & y) > 1-edgeTol)
150  {
151  minY = min(minY, eMag);
152  maxY = max(maxY, eMag);
153  nY++;
154  }
155  else if (mag(eVec & z) > 1-edgeTol)
156  {
157  minZ = min(minZ, eMag);
158  maxZ = max(maxZ, eMag);
159  nZ++;
160  }
161  else
162  {
163  minOther = min(minOther, eMag);
164  maxOther = max(maxOther, eMag);
165  }
166  }
167 
168  Info<< "Mesh bounding box:" << boundBox(mesh.points()) << nl << nl
169  << "Mesh edge statistics:" << nl
170  << " x aligned : number:" << nX << "\tminLen:" << minX
171  << "\tmaxLen:" << maxX << nl
172  << " y aligned : number:" << nY << "\tminLen:" << minY
173  << "\tmaxLen:" << maxY << nl
174  << " z aligned : number:" << nZ << "\tminLen:" << minZ
175  << "\tmaxLen:" << maxZ << nl
176  << " other : number:" << mesh.nEdges() - nX - nY - nZ
177  << "\tminLen:" << minOther
178  << "\tmaxLen:" << maxOther << nl << endl;
179 
180  if (excludeCmpt == 0)
181  {
182  return min(minY, min(minZ, minOther));
183  }
184  else if (excludeCmpt == 1)
185  {
186  return min(minX, min(minZ, minOther));
187  }
188  else if (excludeCmpt == 2)
189  {
190  return min(minX, min(minY, minOther));
191  }
192  else
193  {
194  return min(minX, min(minY, min(minZ, minOther)));
195  }
196 }
197 
198 
199 // Adds empty patch if not yet there. Returns patchID.
200 label addPatch(polyMesh& mesh, const word& patchName)
201 {
202  label patchi = mesh.boundaryMesh().findPatchID(patchName);
203 
204  if (patchi == -1)
205  {
207 
208  List<polyPatch*> newPatches(patches.size() + 1);
209 
210  // Add empty patch as 0th entry (Note: only since subsetMesh wants this)
211  patchi = 0;
212 
213  newPatches[patchi] =
214  new emptyPolyPatch
215  (
216  Foam::word(patchName),
217  0,
219  patchi,
220  patches,
221  emptyPolyPatch::typeName
222  );
223 
224  forAll(patches, i)
225  {
226  const polyPatch& pp = patches[i];
227 
228  newPatches[i+1] =
229  pp.clone
230  (
231  patches,
232  i+1,
233  pp.size(),
234  pp.start()
235  ).ptr();
236  }
237 
239  mesh.addPatches(newPatches);
240 
241  Info<< "Created patch oldInternalFaces at " << patchi << endl;
242  }
243  else
244  {
245  Info<< "Reusing patch oldInternalFaces at " << patchi << endl;
246  }
247 
248 
249  return patchi;
250 }
251 
252 
253 // Take surface and select cells based on surface curvature.
254 void selectCurvatureCells
255 (
256  const polyMesh& mesh,
257  const fileName& surfName,
258  const triSurfaceSearch& querySurf,
259  const scalar nearDist,
260  const scalar curvature,
261  cellSet& cells
262 )
263 {
264  // Use surfaceToCell to do actual calculation.
265 
266  // Since we're adding make sure set is on disk.
267  cells.write();
268 
269  // Take centre of cell 0 as outside point since info not used.
270 
271  surfaceToCell cutSource
272  (
273  mesh,
274  surfName,
275  querySurf.surface(),
276  querySurf,
277  pointField(1, mesh.cellCentres()[0]),
278  false, // includeCut
279  false, // includeInside
280  false, // includeOutside
281  false, // geometricOnly
282  nearDist,
283  curvature
284  );
285 
286  cutSource.applyToSet(topoSetSource::ADD, cells);
287 }
288 
289 
290 // cutCells contains currently selected cells to be refined. Add neighbours
291 // on the inside or outside to them.
292 void addCutNeighbours
293 (
294  const polyMesh& mesh,
295  const bool selectInside,
296  const bool selectOutside,
297  const labelHashSet& inside,
298  const labelHashSet& outside,
299  labelHashSet& cutCells
300 )
301 {
302  // Pick up face neighbours of cutCells
303 
304  labelHashSet addCutFaces(cutCells.size());
305 
306  for (const label celli : cutCells)
307  {
308  const labelList& cFaces = mesh.cells()[celli];
309 
310  forAll(cFaces, i)
311  {
312  const label facei = cFaces[i];
313 
314  if (mesh.isInternalFace(facei))
315  {
316  label nbr = mesh.faceOwner()[facei];
317 
318  if (nbr == celli)
319  {
320  nbr = mesh.faceNeighbour()[facei];
321  }
322 
323  if (selectInside && inside.found(nbr))
324  {
325  addCutFaces.insert(nbr);
326  }
327  else if (selectOutside && outside.found(nbr))
328  {
329  addCutFaces.insert(nbr);
330  }
331  }
332  }
333  }
334 
335  Info<< " Selected an additional " << addCutFaces.size()
336  << " neighbours of cutCells to refine" << endl;
337 
338  for (const label facei : addCutFaces)
339  {
340  cutCells.insert(facei);
341  }
342 }
343 
344 
345 // Return true if any cells had to be split to keep a difference between
346 // neighbouring refinement levels < limitDiff.
347 // Gets cells which will be refined (so increase the refinement level) and
348 // updates it.
349 bool limitRefinementLevel
350 (
351  const primitiveMesh& mesh,
352  const label limitDiff,
353  const labelHashSet& excludeCells,
354  const labelList& refLevel,
355  labelHashSet& cutCells
356 )
357 {
358  // Do simple check on validity of refinement level.
359  forAll(refLevel, celli)
360  {
361  if (!excludeCells.found(celli))
362  {
363  const labelList& cCells = mesh.cellCells()[celli];
364 
365  forAll(cCells, i)
366  {
367  label nbr = cCells[i];
368 
369  if (!excludeCells.found(nbr))
370  {
371  if (refLevel[celli] - refLevel[nbr] >= limitDiff)
372  {
374  << "Level difference between neighbouring cells "
375  << celli << " and " << nbr
376  << " greater than or equal to " << limitDiff << endl
377  << "refLevels:" << refLevel[celli] << ' '
378  << refLevel[nbr] << abort(FatalError);
379  }
380  }
381  }
382  }
383  }
384 
385 
386  labelHashSet addCutCells(cutCells.size());
387 
388  for (const label celli : cutCells)
389  {
390  // celli will be refined.
391  const labelList& cCells = mesh.cellCells()[celli];
392 
393  forAll(cCells, i)
394  {
395  const label nbr = cCells[i];
396 
397  if (!excludeCells.found(nbr) && !cutCells.found(nbr))
398  {
399  if (refLevel[celli] + 1 - refLevel[nbr] >= limitDiff)
400  {
401  addCutCells.insert(nbr);
402  }
403  }
404  }
405  }
406 
407  if (addCutCells.size())
408  {
409  // Add cells to cutCells.
410 
411  Info<< "Added an additional " << addCutCells.size() << " cells"
412  << " to satisfy 1:" << limitDiff << " refinement level"
413  << endl;
414 
415  for (const label celli : addCutCells)
416  {
417  cutCells.insert(celli);
418  }
419  return true;
420  }
421 
422  Info<< "Added no additional cells"
423  << " to satisfy 1:" << limitDiff << " refinement level"
424  << endl;
425 
426  return false;
427 }
428 
429 
430 // Do all refinement (i.e. refCells) according to refineDict and update
431 // refLevel afterwards for added cells
432 void doRefinement
433 (
434  polyMesh& mesh,
435  const dictionary& refineDict,
436  const labelHashSet& refCells,
437  labelList& refLevel
438 )
439 {
440  label oldCells = mesh.nCells();
441 
442  // Multi-iteration, multi-direction topology modifier.
443  multiDirRefinement multiRef
444  (
445  mesh,
446  refCells.toc(),
447  refineDict
448  );
449 
450  //
451  // Update refLevel for split cells
452  //
453 
454  refLevel.setSize(mesh.nCells());
455 
456  for (label celli = oldCells; celli < mesh.nCells(); celli++)
457  {
458  refLevel[celli] = 0;
459  }
460 
461  const labelListList& addedCells = multiRef.addedCells();
462 
463  forAll(addedCells, oldCelli)
464  {
465  const labelList& added = addedCells[oldCelli];
466 
467  if (added.size())
468  {
469  // Give all cells resulting from split the refinement level
470  // of the master.
471  label masterLevel = ++refLevel[oldCelli];
472 
473  forAll(added, i)
474  {
475  refLevel[added[i]] = masterLevel;
476  }
477  }
478  }
479 }
480 
481 
482 // Subset mesh and update refLevel and cutCells
483 void subsetMesh
484 (
485  polyMesh& mesh,
486  const label writeMesh,
487  const label patchi, // patchID for exposed faces
488  const labelHashSet& cellsToRemove,
489  cellSet& cutCells,
490  labelIOList& refLevel
491 )
492 {
493  removeCells cellRemover(mesh);
494 
495  labelList cellLabels(cellsToRemove.toc());
496 
497  Info<< "Mesh has:" << mesh.nCells() << " cells."
498  << " Removing:" << cellLabels.size() << " cells" << endl;
499 
500  // exposed faces
501  labelList exposedFaces(cellRemover.getExposedFaces(cellLabels));
502 
503  polyTopoChange meshMod(mesh);
504  cellRemover.setRefinement
505  (
506  cellLabels,
507  exposedFaces,
508  labelList(exposedFaces.size(), patchi),
509  meshMod
510  );
511 
512  // Do all changes
513  Info<< "Morphing ..." << endl;
514 
515  const Time& runTime = mesh.time();
516 
517  autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
518 
519  if (morphMap().hasMotionPoints())
520  {
521  mesh.movePoints(morphMap().preMotionPoints());
522  }
523 
524  // Update topology on cellRemover
525  cellRemover.updateMesh(morphMap());
526 
527  // Update refLevel for removed cells.
528  const labelList& cellMap = morphMap().cellMap();
529 
530  labelList newRefLevel(cellMap.size());
531 
532  forAll(cellMap, i)
533  {
534  newRefLevel[i] = refLevel[cellMap[i]];
535  }
536 
537  // Transfer back to refLevel
538  refLevel.transfer(newRefLevel);
539 
540  if (writeMesh)
541  {
542  Info<< "Writing refined mesh to time " << runTime.timeName() << nl
543  << endl;
544 
546  mesh.write();
547  refLevel.write();
548  }
549 
550  // Update cutCells for removed cells.
551  cutCells.updateMesh(morphMap());
552 }
553 
554 
555 // Divide the cells according to status compared to surface. Constructs sets:
556 // - cutCells : all cells cut by surface
557 // - inside : all cells inside surface
558 // - outside : ,, outside ,,
559 // and a combined set:
560 // - selected : sum of above according to selectCut/Inside/Outside flags.
561 void classifyCells
562 (
563  const polyMesh& mesh,
564  const fileName& surfName,
565  const triSurfaceSearch& querySurf,
566  const pointField& outsidePts,
567 
568  const bool selectCut,
569  const bool selectInside,
570  const bool selectOutside,
571 
572  const label nCutLayers,
573 
574  cellSet& inside,
575  cellSet& outside,
576  cellSet& cutCells,
577  cellSet& selected
578 )
579 {
580  // Cut faces with surface and classify cells
582  (
583  mesh,
584  surfName,
585  querySurf.surface(),
586  querySurf,
587  outsidePts,
588 
589  nCutLayers,
590 
591  inside,
592  outside,
593  cutCells
594  );
595 
596  // Combine wanted parts into selected
597  if (selectCut)
598  {
599  selected.addSet(cutCells);
600  }
601  if (selectInside)
602  {
603  selected.addSet(inside);
604  }
605  if (selectOutside)
606  {
607  selected.addSet(outside);
608  }
609 
610  Info<< "Determined cell status:" << endl
611  << " inside :" << inside.size() << endl
612  << " outside :" << outside.size() << endl
613  << " cutCells:" << cutCells.size() << endl
614  << " selected:" << selected.size() << endl
615  << endl;
616 
617  writeSet(inside, "inside cells");
618  writeSet(outside, "outside cells");
619  writeSet(cutCells, "cut cells");
620  writeSet(selected, "selected cells");
621 }
622 
623 
624 
625 int main(int argc, char *argv[])
626 {
628  (
629  "Refine cells near to a surface"
630  );
632 
633  #include "setRootCase.H"
634  #include "createTime.H"
635  #include "createPolyMesh.H"
636 
637  // If necessary add oldInternalFaces patch
638  label newPatchi = addPatch(mesh, "oldInternalFaces");
639 
640 
641  //
642  // Read motionProperties dictionary
643  //
644 
645  Info<< "Checking for motionProperties\n" << endl;
646 
647  IOobject motionObj
648  (
649  "motionProperties",
650  runTime.constant(),
651  mesh,
654  );
655 
656  // corrector for mesh motion
657  twoDPointCorrector* correct2DPtr = nullptr;
658 
659  if (motionObj.typeHeaderOk<IOdictionary>(true))
660  {
661  Info<< "Reading " << runTime.constant() / "motionProperties"
662  << endl << endl;
663 
664  IOdictionary motionProperties(motionObj);
665 
666  if (motionProperties.get<bool>("twoDMotion"))
667  {
668  Info<< "Correcting for 2D motion" << endl << endl;
669  correct2DPtr = new twoDPointCorrector(mesh);
670  }
671  }
672 
673  IOdictionary refineDict
674  (
675  IOobject
676  (
677  "snappyRefineMeshDict",
678  runTime.system(),
679  mesh,
682  )
683  );
684 
685  fileName surfName(refineDict.get<fileName>("surface"));
686  surfName.expand();
687  const label nCutLayers(refineDict.get<label>("nCutLayers"));
688  const label cellLimit(refineDict.get<label>("cellLimit"));
689  const bool selectCut(refineDict.get<bool>("selectCut"));
690  const bool selectInside(refineDict.get<bool>("selectInside"));
691  const bool selectOutside(refineDict.get<bool>("selectOutside"));
692  const bool selectHanging(refineDict.get<bool>("selectHanging"));
693 
694  const scalar minEdgeLen(refineDict.get<scalar>("minEdgeLen"));
695  const scalar maxEdgeLen(refineDict.get<scalar>("maxEdgeLen"));
696  const scalar curvature(refineDict.get<scalar>("curvature"));
697  const scalar curvDist(refineDict.get<scalar>("curvatureDistance"));
698  pointField outsidePts(refineDict.lookup("outsidePoints"));
699  const label refinementLimit(refineDict.get<label>("splitLevel"));
700  const bool writeMesh(refineDict.get<bool>("writeMesh"));
701 
702  Info<< "Cells to be used for meshing (0=false, 1=true):" << nl
703  << " cells cut by surface : " << selectCut << nl
704  << " cells inside of surface : " << selectInside << nl
705  << " cells outside of surface : " << selectOutside << nl
706  << " hanging cells : " << selectHanging << nl
707  << endl;
708 
709 
710  if (nCutLayers > 0 && selectInside)
711  {
713  << "Illogical settings : Both nCutLayers>0 and selectInside true."
714  << endl
715  << "This would mean that inside cells get removed but should be"
716  << " included in final mesh" << endl;
717  }
718 
719  // Surface.
720  triSurface surf(surfName);
721 
722  // Search engine on surface
723  triSurfaceSearch querySurf(surf);
724 
725  // Search engine on mesh. No face decomposition since mesh unwarped.
727 
728  // Check all 'outside' points
729  forAll(outsidePts, outsidei)
730  {
731  const point& outsidePoint = outsidePts[outsidei];
732 
733  if (queryMesh.findCell(outsidePoint, -1, false) == -1)
734  {
736  << "outsidePoint " << outsidePoint
737  << " is not inside any cell"
738  << exit(FatalError);
739  }
740  }
741 
742 
743 
744  // Current refinement level. Read if present.
745  labelIOList refLevel
746  (
747  IOobject
748  (
749  "refinementLevel",
750  runTime.timeName(),
752  mesh,
755  ),
757  );
758 
759  label maxLevel = max(refLevel);
760 
761  if (maxLevel > 0)
762  {
763  Info<< "Read existing refinement level from file "
764  << refLevel.objectPath() << nl
765  << " min level : " << min(refLevel) << nl
766  << " max level : " << maxLevel << nl
767  << endl;
768  }
769  else
770  {
771  Info<< "Created zero refinement level in file "
772  << refLevel.objectPath() << nl
773  << endl;
774  }
775 
776 
777 
778 
779  // Print edge stats on original mesh. Leave out 2d-normal direction
780  direction normalDir(getNormalDir(correct2DPtr));
781  scalar meshMinEdgeLen = getEdgeStats(mesh, normalDir);
782 
783  while (meshMinEdgeLen > minEdgeLen)
784  {
785  // Get inside/outside/cutCells cellSets.
786  cellSet inside(mesh, "inside", mesh.nCells()/10);
787  cellSet outside(mesh, "outside", mesh.nCells()/10);
788  cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
789  cellSet selected(mesh, "selected", mesh.nCells()/10);
790 
791  classifyCells
792  (
793  mesh,
794  surfName,
795  querySurf,
796  outsidePts,
797 
798  selectCut, // for determination of selected
799  selectInside, // for determination of selected
800  selectOutside, // for determination of selected
801 
802  nCutLayers, // How many layers of cutCells to include
803 
804  inside,
805  outside,
806  cutCells,
807  selected // not used but determined anyway.
808  );
809 
810  Info<< " Selected " << cutCells.name() << " with "
811  << cutCells.size() << " cells" << endl;
812 
813  if ((curvDist > 0) && (meshMinEdgeLen < maxEdgeLen))
814  {
815  // Done refining enough close to surface. Now switch to more
816  // intelligent refinement where only cutCells on surface curvature
817  // are refined.
818  cellSet curveCells(mesh, "curveCells", mesh.nCells()/10);
819 
820  selectCurvatureCells
821  (
822  mesh,
823  surfName,
824  querySurf,
825  maxEdgeLen,
826  curvature,
827  curveCells
828  );
829 
830  Info<< " Selected " << curveCells.name() << " with "
831  << curveCells.size() << " cells" << endl;
832 
833  // Add neighbours to cutCells. This is if selectCut is not
834  // true and so outside and/or inside cells get exposed there is
835  // also refinement in them.
836  if (!selectCut)
837  {
838  addCutNeighbours
839  (
840  mesh,
841  selectInside,
842  selectOutside,
843  inside,
844  outside,
845  cutCells
846  );
847  }
848 
849  // Subset cutCells to only curveCells
850  cutCells.subset(curveCells);
851 
852  Info<< " Removed cells not on surface curvature. Selected "
853  << cutCells.size() << endl;
854  }
855 
856 
857  if (nCutLayers > 0)
858  {
859  // Subset mesh to remove inside cells altogether. Updates cutCells,
860  // refLevel.
861  subsetMesh(mesh, writeMesh, newPatchi, inside, cutCells, refLevel);
862  }
863 
864 
865  // Added cells from 2:1 refinement level restriction.
866  while
867  (
868  limitRefinementLevel
869  (
870  mesh,
871  refinementLimit,
872  labelHashSet(),
873  refLevel,
874  cutCells
875  )
876  )
877  {}
878 
879 
880  Info<< " Current cells : " << mesh.nCells() << nl
881  << " Selected for refinement :" << cutCells.size() << nl
882  << endl;
883 
884  if (cutCells.empty())
885  {
886  Info<< "Stopping refining since 0 cells selected to be refined ..."
887  << nl << endl;
888  break;
889  }
890 
891  if ((mesh.nCells() + 8*cutCells.size()) > cellLimit)
892  {
893  Info<< "Stopping refining since cell limit reached ..." << nl
894  << "Would refine from " << mesh.nCells()
895  << " to " << mesh.nCells() + 8*cutCells.size() << " cells."
896  << nl << endl;
897  break;
898  }
899 
900  doRefinement
901  (
902  mesh,
903  refineDict,
904  cutCells,
905  refLevel
906  );
907 
908  Info<< " After refinement:" << mesh.nCells() << nl
909  << endl;
910 
911  if (writeMesh)
912  {
913  Info<< " Writing refined mesh to time " << runTime.timeName()
914  << nl << endl;
915 
917  mesh.write();
918  refLevel.write();
919  }
920 
921  // Update mesh edge stats.
922  meshMinEdgeLen = getEdgeStats(mesh, normalDir);
923  }
924 
925 
926  if (selectHanging)
927  {
928  // Get inside/outside/cutCells cellSets.
929  cellSet inside(mesh, "inside", mesh.nCells()/10);
930  cellSet outside(mesh, "outside", mesh.nCells()/10);
931  cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
932  cellSet selected(mesh, "selected", mesh.nCells()/10);
933 
934  classifyCells
935  (
936  mesh,
937  surfName,
938  querySurf,
939  outsidePts,
940 
941  selectCut,
942  selectInside,
943  selectOutside,
944 
945  nCutLayers,
946 
947  inside,
948  outside,
949  cutCells,
950  selected
951  );
952 
953 
954  // Find any cells which have all their points on the outside of the
955  // selected set and refine them
956  labelHashSet hanging = surfaceSets::getHangingCells(mesh, selected);
957 
958  Info<< "Detected " << hanging.size() << " hanging cells"
959  << " (cells with all points on"
960  << " outside of cellSet 'selected').\nThese would probably result"
961  << " in flattened cells when snapping the mesh to the surface"
962  << endl;
963 
964  Info<< "Refining " << hanging.size() << " hanging cells" << nl
965  << endl;
966 
967  // Added cells from 2:1 refinement level restriction.
968  while
969  (
970  limitRefinementLevel
971  (
972  mesh,
973  refinementLimit,
974  labelHashSet(),
975  refLevel,
976  hanging
977  )
978  )
979  {}
980 
981  doRefinement(mesh, refineDict, hanging, refLevel);
982 
983  Info<< "Writing refined mesh to time " << runTime.timeName() << nl
984  << endl;
985 
986  // Write final mesh
988  mesh.write();
989  refLevel.write();
990 
991  }
992  else if (!writeMesh)
993  {
994  Info<< "Writing refined mesh to time " << runTime.timeName() << nl
995  << endl;
996 
997  // Write final mesh. (will have been written already if writeMesh=true)
999  mesh.write();
1000  refLevel.write();
1001  }
1002 
1003 
1004  Info<< "End\n" << endl;
1005 
1006  return 0;
1007 }
1008 
1009 
1010 // ************************************************************************* //
Foam::IOobject::NO_WRITE
@ NO_WRITE
Definition: IOobject.H:191
Foam::polyMesh::addPatches
void addPatches(PtrList< polyPatch > &plist, const bool validBoundary=true)
Definition: polyMesh.C:954
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:63
Foam::IOdictionary
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::surfaceSets::getHangingCells
static labelHashSet getHangingCells(const primitiveMesh &mesh, const labelHashSet &internalCells)
Definition: surfaceSets.C:274
Foam::polyMesh::points
virtual const pointField & points() const
Definition: polyMesh.C:1062
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:165
Foam::topoSetSource::ADD
@ ADD
Add elements to current set.
Definition: topoSetSource.H:99
Foam::IOobject::AUTO_WRITE
@ AUTO_WRITE
Definition: IOobject.H:190
Foam::surfaceSets::getSurfaceSets
static void getSurfaceSets(const polyMesh &mesh, const fileName &surfName, const triSurface &surf, const triSurfaceSearch &querySurf, const pointField &outsidePts, const label nCutLayers, labelHashSet &inside, labelHashSet &outside, labelHashSet &cut)
Definition: surfaceSets.C:215
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:63
Foam::meshSearch
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search.
Definition: meshSearch.H:56
Foam::fileName
A class for handling file names.
Definition: fileName.H:71
Foam::fvMesh::write
virtual bool write(const bool valid=true) const
Definition: fvMesh.C:1034
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:59
Foam::twoDPointCorrector::planeNormal
const vector & planeNormal() const
Definition: twoDPointCorrector.C:242
Foam::polyMesh::defaultRegion
static word defaultRegion
Definition: polyMesh.H:314
Foam::Zero
static constexpr const zero Zero
Definition: zero.H:131
Foam::removeCells
Given list of cells to remove, insert all the topology changes.
Definition: removeCells.H:59
cellToCell.H
mapPolyMesh.H
polyTopoChanger.H
polyTopoChange.H
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:773
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:131
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:95
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:59
Foam::argList::addNote
static void addNote(const string &note)
Definition: argList.C:405
Foam::primitiveMesh::nEdges
label nEdges() const
Definition: primitiveMeshI.H:60
Foam::topoSet::subset
virtual void subset(const topoSet &set)
Definition: topoSet.C:552
multiDirRefinement.H
Foam::fvMesh::movePoints
virtual tmp< scalarField > movePoints(const pointField &)
Definition: fvMesh.C:858
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Definition: polyMesh.H:440
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:100
Foam::primitiveMesh::edges
const edgeList & edges() const
Definition: primitiveMeshEdges.C:498
removeCells.H
triSurface.H
polyMesh.H
Foam::HashSet
A HashTable with keys but without contents that is similar to std::unordered_set.
Definition: HashSet.H:73
Foam::triSurfaceSearch
Helper class to search on triSurface.
Definition: triSurfaceSearch.H:54
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Definition: hashSets.C:26
surfaceToCell.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:73
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
OFstream.H
Foam::topoSet::addSet
virtual void addSet(const topoSet &set)
Definition: topoSet.C:559
Foam::twoDPointCorrector
Class applies a two-dimensional correction to mesh motion point field.
Definition: twoDPointCorrector.H:59
Foam::primitiveMesh::nCells
label nCells() const noexcept
Definition: primitiveMeshI.H:89
Foam::Field
Generic templated field type.
Definition: Field.H:59
Foam::regIOobject::write
virtual bool write(const bool valid=true) const
Definition: regIOobjectWrite.C:125
surfaceToPoint.H
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:72
Foam::Info
messageStream Info
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:64
Foam::List::setSize
void setSize(const label n)
Definition: List.H:218
argList.H
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Definition: polyMesh.C:1100
surfaceSets.H
Foam::List::transfer
void transfer(List< T > &list)
Foam::IOobject::READ_IF_PRESENT
@ READ_IF_PRESENT
Definition: IOobject.H:183
Foam::primitiveMesh::cellCells
const labelListList & cellCells() const
Definition: primitiveMeshCellCells.C:95
Foam::multiDirRefinement
Does multiple pass refinement to refine cells in multiple directions.
Definition: multiDirRefinement.H:72
Foam::polyBoundaryMesh::findPatchID
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Definition: polyBoundaryMesh.C:758
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Definition: hashSets.C:40
Foam::surfaceToCell
A topoSetCellSource to select cells based on relation to a surface given by an external file.
Definition: surfaceToCell.H:238
Foam::dictionary::lookup
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionary.C:379
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:119
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam
Definition: atmBoundaryLayer.C:26
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Foam::cellSet
A collection of cell labels.
Definition: cellSet.H:47
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:47
Foam::polyPatch::start
label start() const
Definition: polyPatch.H:357
emptyPolyPatch.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Foam::polyMesh::removeBoundary
void removeBoundary()
Definition: polyMeshClear.C:32
Foam::emptyPolyPatch
Empty front and back plane patch. Used for 2-D geometries.
Definition: emptyPolyPatch.H:46
Foam::IOobject::name
const word & name() const noexcept
Definition: IOobjectI.H:58
Foam::IOstream::defaultPrecision
static unsigned int defaultPrecision() noexcept
Definition: IOstream.H:338
Time.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:49
setRootCase.H
pointToCell.H
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:78
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const noexcept
Definition: primitiveMeshI.H:96
Foam::TimePaths::system
const word & system() const
Definition: TimePathsI.H:95
FatalErrorInFunction
#define FatalErrorInFunction
Definition: error.H:465
Foam::cellSet::updateMesh
virtual void updateMesh(const mapPolyMesh &morphMap)
Definition: cellSet.C:181
meshSearch.H
Foam::nl
constexpr char nl
Definition: Ostream.H:424
Foam::Vector< scalar >
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const noexcept
Definition: primitiveMeshI.H:71
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:58
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::string::expand
string & expand(const bool allowEmpty=false)
Definition: string.C:166
labelIOList.H
Foam::triSurfaceSearch::surface
const triSurface & surface() const
Definition: triSurfaceSearch.H:125
Foam::constant::electromagnetic::e
const dimensionedScalar e
Definition: createFields.H:11
Foam::IOList< label >
Foam::direction
uint8_t direction
Definition: direction.H:46
createTime.H
cellToPoint.H
Foam::IOobject::MUST_READ_IF_MODIFIED
@ MUST_READ_IF_MODIFIED
Definition: IOobject.H:182
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:59
x
x
Definition: LISASMDCalcMethod2.H:52
triSurfaceSearch.H
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:57
Foam::polyPatch::clone
virtual autoPtr< polyPatch > clone(const labelList &faceCells) const
Definition: polyPatch.H:231
Foam::fvMesh::time
const Time & time() const
Definition: fvMesh.H:276
twoDPointCorrector.H
Foam::polyMesh::FACE_PLANES
@ FACE_PLANES
Definition: polyMesh.H:98
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
cellSet.H
Foam::argList::noParallel
static void noParallel()
Definition: argList.C:503
Foam::IOobject::objectPath
fileName objectPath() const
Definition: IOobjectI.H:207
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys and label hasher.
Definition: HashSet.H:85
Foam::TimePaths::constant
const word & constant() const
Definition: TimePathsI.H:89
createPolyMesh.H
Required Variables.
WarningInFunction
#define WarningInFunction
Definition: messageStream.H:353
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Definition: polyMesh.C:1106
y
scalar y
Definition: LISASMDCalcMethod1.H:14
pointSet.H
Foam::primitiveMesh
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:74