refinementLevel.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) 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  refinementLevel
29 
30 Group
31  grpMeshAdvancedUtilities
32 
33 Description
34  Attempt to determine the refinement levels of a refined cartesian mesh.
35  Run BEFORE snapping.
36 
37  Writes
38  - volScalarField 'refinementLevel' with current refinement level.
39  - cellSet 'refCells' which are the cells that need to be refined to satisfy
40  2:1 refinement.
41 
42  Works by dividing cells into volume bins.
43 
44 \*---------------------------------------------------------------------------*/
45 
46 #include "argList.H"
47 #include "Time.H"
48 #include "polyMesh.H"
49 #include "cellSet.H"
50 #include "SortableList.H"
51 #include "labelIOList.H"
52 #include "fvMesh.H"
53 #include "volFields.H"
54 
55 using namespace Foam;
56 
57 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
58 
59 // Return true if any cells had to be split to keep a difference between
60 // neighbouring refinement levels < limitDiff. Puts cells into refCells and
61 // update refLevel to account for refinement.
62 bool limitRefinementLevel
63 (
64  const primitiveMesh& mesh,
65  labelList& refLevel,
66  cellSet& refCells
67 )
68 {
69  const labelListList& cellCells = mesh.cellCells();
70 
71  label oldNCells = refCells.size();
72 
73  forAll(cellCells, celli)
74  {
75  const labelList& cCells = cellCells[celli];
76 
77  forAll(cCells, i)
78  {
79  if (refLevel[cCells[i]] > (refLevel[celli]+1))
80  {
81  // Found neighbour with >=2 difference in refLevel.
82  refCells.insert(celli);
83  refLevel[celli]++;
84  break;
85  }
86  }
87  }
88 
89  if (refCells.size() > oldNCells)
90  {
91  Info<< "Added an additional " << refCells.size() - oldNCells
92  << " cells to satisfy 1:2 refinement level"
93  << endl;
94 
95  return true;
96  }
97 
98  return false;
99 }
100 
101 
102 int main(int argc, char *argv[])
103 {
105  (
106  "Attempt to determine refinement levels of a refined cartesian mesh.\n"
107  "Run BEFORE snapping!"
108  );
109 
111  (
112  "readLevel",
113  "Read level from refinementLevel file"
114  );
115 
116  #include "setRootCase.H"
117  #include "createTime.H"
118  #include "createPolyMesh.H"
119 
120  Info<< "Dividing cells into bins depending on cell volume.\nThis will"
121  << " correspond to refinement levels for a mesh with only 2x2x2"
122  << " refinement\n"
123  << "The upper range for every bin is always 1.1 times the lower range"
124  << " to allow for some truncation error."
125  << nl << endl;
126 
127  const bool readLevel = args.found("readLevel");
128 
129  const scalarField& vols = mesh.cellVolumes();
130 
131  SortableList<scalar> sortedVols(vols);
132 
133  // All cell labels, sorted per bin.
135 
136  // Lower/upper limits
137  DynamicList<scalar> lowerLimits;
138  DynamicList<scalar> upperLimits;
139 
140  // Create bin0. Have upperlimit as factor times lowerlimit.
141  bins.append(DynamicList<label>());
142  lowerLimits.append(sortedVols[0]);
143  upperLimits.append(1.1 * lowerLimits.last());
144 
145  forAll(sortedVols, i)
146  {
147  if (sortedVols[i] > upperLimits.last())
148  {
149  // New value outside of current bin
150 
151  // Shrink old bin.
152  DynamicList<label>& bin = bins.last();
153 
154  bin.shrink();
155 
156  Info<< "Collected " << bin.size() << " elements in bin "
157  << lowerLimits.last() << " .. "
158  << upperLimits.last() << endl;
159 
160  // Create new bin.
161  bins.append(DynamicList<label>());
162  lowerLimits.append(sortedVols[i]);
163  upperLimits.append(1.1 * lowerLimits.last());
164 
165  Info<< "Creating new bin " << lowerLimits.last()
166  << " .. " << upperLimits.last()
167  << endl;
168  }
169 
170  // Append to current bin.
171  DynamicList<label>& bin = bins.last();
172 
173  bin.append(sortedVols.indices()[i]);
174  }
175  Info<< endl;
176 
177  bins.last().shrink();
178  bins.shrink();
179  lowerLimits.shrink();
180  upperLimits.shrink();
181 
182 
183  //
184  // Write to cellSets.
185  //
186 
187  Info<< "Volume bins:" << nl;
188  forAll(bins, binI)
189  {
190  const DynamicList<label>& bin = bins[binI];
191 
192  cellSet cells(mesh, "vol" + name(binI), bin.size());
193  cells.insert(bin);
194 
195  Info<< " " << lowerLimits[binI] << " .. " << upperLimits[binI]
196  << " : writing " << bin.size() << " cells to cellSet "
197  << cells.name() << endl;
198 
199  cells.write();
200  }
201 
202 
203 
204  //
205  // Convert bins into refinement level.
206  //
207 
208 
209  // Construct fvMesh to be able to construct volScalarField
210 
211  fvMesh fMesh
212  (
213  IOobject
214  (
216  runTime.timeName(),
217  runTime,
220  ),
221  pointField(mesh.points()), // Could we safely re-use the data?
222  faceList(mesh.faces()),
223  cellList(mesh.cells())
224  );
225 
226  // Add the boundary patches
228 
229  polyPatchList newPatches(patches.size());
230 
231  forAll(newPatches, patchi)
232  {
233  newPatches.set
234  (
235  patchi,
236  patches[patchi].clone(fMesh.boundaryMesh())
237  );
238  }
239 
240  fMesh.addFvPatches(newPatches);
241 
242 
243  // Refinement level
244  IOobject refHeader
245  (
246  "refinementLevel",
247  runTime.timeName(),
249  runTime
250  );
251 
252  if (!readLevel && refHeader.typeHeaderOk<labelIOList>(true))
253  {
255  << "Detected " << refHeader.name() << " file in "
256  << polyMesh::defaultRegion << " directory. Please remove to"
257  << " recreate it or use the -readLevel option to use it"
258  << endl;
259  return 1;
260  }
261 
262 
263  labelIOList refLevel
264  (
265  IOobject
266  (
267  "refinementLevel",
268  runTime.timeName(),
269  mesh,
272  ),
274  );
275 
276  if (readLevel)
277  {
278  refLevel = labelIOList(refHeader);
279  }
280 
281  // Construct volScalarField with same info for post processing
282  volScalarField postRefLevel
283  (
284  IOobject
285  (
286  "refinementLevel",
287  runTime.timeName(),
288  mesh,
291  ),
292  fMesh,
294  );
295 
296  // Set cell values
297  forAll(bins, binI)
298  {
299  const DynamicList<label>& bin = bins[binI];
300 
301  forAll(bin, i)
302  {
303  refLevel[bin[i]] = bins.size() - binI - 1;
304  postRefLevel[bin[i]] = refLevel[bin[i]];
305  }
306  }
307 
308  volScalarField::Boundary& postRefLevelBf =
309  postRefLevel.boundaryFieldRef();
310 
311  // For volScalarField: set boundary values to same as cell.
312  // Note: could also put
313  // zeroGradient b.c. on postRefLevel and do evaluate.
314  forAll(postRefLevel.boundaryField(), patchi)
315  {
316  const polyPatch& pp = patches[patchi];
317 
318  fvPatchScalarField& bField = postRefLevelBf[patchi];
319 
320  Info<< "Setting field for patch "<< endl;
321 
322  forAll(bField, facei)
323  {
324  label own = mesh.faceOwner()[pp.start() + facei];
325 
326  bField[facei] = postRefLevel[own];
327  }
328  }
329 
330  Info<< "Determined current refinement level and writing to "
331  << postRefLevel.name() << " (as volScalarField; for post processing)"
332  << nl
333  << polyMesh::defaultRegion/refLevel.name()
334  << " (as labelIOList; for meshing)" << nl
335  << endl;
336 
337  refLevel.write();
338  postRefLevel.write();
339 
340 
341  // Find out cells to refine to keep to 2:1 refinement level restriction
342 
343  // Cells to refine
344  cellSet refCells(mesh, "refCells", 100);
345 
346  while
347  (
348  limitRefinementLevel
349  (
350  mesh,
351  refLevel, // current refinement level
352  refCells // cells to refine
353  )
354  )
355  {}
356 
357  if (refCells.size())
358  {
359  Info<< "Collected " << refCells.size() << " cells that need to be"
360  << " refined to get closer to overall 2:1 refinement level limit"
361  << nl
362  << "Written cells to be refined to cellSet " << refCells.name()
363  << nl << endl;
364 
365  refCells.write();
366 
367  Info<< "After refinement this tool can be run again to see if the 2:1"
368  << " limit is observed all over the mesh" << nl << endl;
369  }
370  else
371  {
372  Info<< "All cells in the mesh observe the 2:1 refinement level limit"
373  << nl << endl;
374  }
375 
376  Info<< "\nEnd\n" << endl;
377  return 0;
378 }
379 
380 
381 // ************************************************************************* //
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:462
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
Required Variables.
List< cell > cellList
List of cell.
Definition: cellListFwd.H:39
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:162
A list that is sorted upon construction or when explicitly requested with the sort() method...
Definition: SortableList.H:56
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:75
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:374
const cellList & cells() const
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:227
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1073
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:331
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
IOList< label > labelIOList
IO for a List of label.
Definition: labelIOList.H:32
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
const cellShapeList & cells
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:584
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:397
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:113
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1111
virtual bool write(const bool writeOnProc=true) const
Write using setting from DB.
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:570
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1098
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:770
DynamicList< T, SizeMin > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:432
T & last()
Access last element of the list, position [size()-1].
Definition: UList.H:828
#define WarningInFunction
Report a warning using Foam::Warning.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
label nCells() const noexcept
Number of mesh cells.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
A collection of cell labels.
Definition: cellSet.H:47
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:79
const polyBoundaryMesh & patches
Nothing to be read.
Automatically write from objectRegistry::writeObject()
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
messageStream Info
Information stream (stdout output on master, null elsewhere)
List< label > labelList
A List of labels.
Definition: List.H:62
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
Foam::argList args(argc, argv)
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:171
const labelListList & cellCells() const
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
const scalarField & cellVolumes() const
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:133