layerParameters.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-2014 OpenFOAM Foundation
6  \\/ M anipulation |
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 "layerParameters.H"
27 #include "polyBoundaryMesh.H"
28 #include "unitConversion.H"
29 #include "refinementSurfaces.H"
30 #include "searchableSurfaces.H"
31 #include "medialAxisMeshMover.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 const Foam::scalar Foam::layerParameters::defaultConcaveAngle = 90;
36 
37 
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 
40 Foam::scalar Foam::layerParameters::layerExpansionRatio
41 (
42  const label n,
43  const scalar totalOverFirst
44 ) const
45 {
46  if (n <= 1)
47  {
48  return 1.0;
49  }
50 
51  //scalar totalOverFirst = totalThickness/firstLayerThickess;
52 
53  const label maxIters = 10;
54  const scalar tol = 1e-8;
55 
56 
57  if (mag(n-totalOverFirst) < tol)
58  {
59  return 1.0;
60  }
61 
62  // Calculate the bounds of the solution
63  scalar minR;
64  scalar maxR;
65 
66  if (totalOverFirst < n)
67  {
68  minR = 0.0;
69  maxR = pow(totalOverFirst/n, 1/(n-1));
70  }
71  else
72  {
73  minR = pow(totalOverFirst/n, 1/(n-1));
74  maxR = totalOverFirst/(n - 1);
75  }
76 
77  //Info<< "Solution bounds = (" << minR << ", " << maxR << ")" << nl << endl;
78 
79  // Starting guess
80  scalar r = 0.5*(minR + maxR);
81 
82  for (label i = 0; i < maxIters; ++i)
83  {
84  const scalar prevr = r;
85 
86  const scalar fx = pow(r, n) - totalOverFirst*r - (1 - totalOverFirst);
87  const scalar dfx = n*pow(r, n - 1) - totalOverFirst;
88 
89  r -= fx/dfx;
90 
91  const scalar error = mag(r - prevr);
92 
93  //Info<< i << " " << r << " Error = " << error << endl;
94 
95  if (error < tol)
96  {
97  break;
98  }
99  }
100  return r;
101 }
102 
103 
104 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
105 
106 // Construct from dictionary
107 Foam::layerParameters::layerParameters
108 (
109  const dictionary& dict,
110  const polyBoundaryMesh& boundaryMesh
111 )
112 :
113  dict_(dict),
114  numLayers_(boundaryMesh.size(), -1),
115  relativeSizes_(dict.lookup("relativeSizes")),
116  layerSpec_(ILLEGAL),
117  firstLayerThickness_(boundaryMesh.size(), -123),
118  finalLayerThickness_(boundaryMesh.size(), -123),
119  thickness_(boundaryMesh.size(), -123),
120  expansionRatio_(boundaryMesh.size(), -123),
121  minThickness_
122  (
123  boundaryMesh.size(),
124  readScalar(dict.lookup("minThickness"))
125  ),
126  featureAngle_(readScalar(dict.lookup("featureAngle"))),
127  concaveAngle_
128  (
129  dict.lookupOrDefault("concaveAngle", defaultConcaveAngle)
130  ),
131  nGrow_(readLabel(dict.lookup("nGrow"))),
132  maxFaceThicknessRatio_
133  (
134  readScalar(dict.lookup("maxFaceThicknessRatio"))
135  ),
136  nBufferCellsNoExtrude_
137  (
138  readLabel(dict.lookup("nBufferCellsNoExtrude"))
139  ),
140  nLayerIter_(readLabel(dict.lookup("nLayerIter"))),
141  nRelaxedIter_(labelMax),
142  additionalReporting_(dict.lookupOrDefault("additionalReporting", false)),
143  meshShrinker_
144  (
145  dict.lookupOrDefault
146  (
147  "meshShrinker",
148  medialAxisMeshMover::typeName
149  )
150  )
151 {
152  // Detect layer specification mode
153 
154  label nSpec = 0;
155 
156  bool haveFirst = dict.found("firstLayerThickness");
157  if (haveFirst)
158  {
159  firstLayerThickness_ = scalarField
160  (
161  boundaryMesh.size(),
162  readScalar(dict.lookup("firstLayerThickness"))
163  );
164  nSpec++;
165  }
166  bool haveFinal = dict.found("finalLayerThickness");
167  if (haveFinal)
168  {
169  finalLayerThickness_ = scalarField
170  (
171  boundaryMesh.size(),
172  readScalar(dict.lookup("finalLayerThickness"))
173  );
174  nSpec++;
175  }
176  bool haveTotal = dict.found("thickness");
177  if (haveTotal)
178  {
179  thickness_ = scalarField
180  (
181  boundaryMesh.size(),
182  readScalar(dict.lookup("thickness"))
183  );
184  nSpec++;
185  }
186  bool haveExp = dict.found("expansionRatio");
187  if (haveExp)
188  {
189  expansionRatio_ = scalarField
190  (
191  boundaryMesh.size(),
192  readScalar(dict.lookup("expansionRatio"))
193  );
194  nSpec++;
195  }
196 
197 
198  if (haveFirst && haveTotal)
199  {
200  layerSpec_ = FIRST_AND_TOTAL;
201  Info<< "Layer thickness specified as first layer and overall thickness."
202  << endl;
203  }
204  else if (haveFirst && haveExp)
205  {
206  layerSpec_ = FIRST_AND_EXPANSION;
207  Info<< "Layer thickness specified as first layer and expansion ratio."
208  << endl;
209  }
210  else if (haveFinal && haveTotal)
211  {
212  layerSpec_ = FINAL_AND_TOTAL;
213  Info<< "Layer thickness specified as final layer and overall thickness."
214  << endl;
215  }
216  else if (haveFinal && haveExp)
217  {
218  layerSpec_ = FINAL_AND_EXPANSION;
219  Info<< "Layer thickness specified as final layer and expansion ratio."
220  << endl;
221  }
222  else if (haveTotal && haveExp)
223  {
224  layerSpec_ = TOTAL_AND_EXPANSION;
225  Info<< "Layer thickness specified as overall thickness"
226  << " and expansion ratio." << endl;
227  }
228 
229 
230  if (layerSpec_ == ILLEGAL || nSpec != 2)
231  {
233  (
234  "layerParameters::layerParameters"
235  "(const dictionary&, const polyBoundaryMesh&)",
236  dict
237  ) << "Over- or underspecified layer thickness."
238  << " Please specify" << nl
239  << " first layer thickness ('firstLayerThickness')"
240  << " and overall thickness ('thickness') or" << nl
241  << " first layer thickness ('firstLayerThickness')"
242  << " and expansion ratio ('expansionRatio') or" << nl
243  << " final layer thickness ('finalLayerThickness')"
244  << " and expansion ratio ('expansionRatio') or" << nl
245  << " final layer thickness ('finalLayerThickness')"
246  << " and overall thickness ('thickness') or" << nl
247  << " overall thickness ('thickness')"
248  << " and expansion ratio ('expansionRatio'"
249  << exit(FatalIOError);
250  }
251 
252 
253  dict.readIfPresent("nRelaxedIter", nRelaxedIter_);
254 
255  if (nLayerIter_ < 0 || nRelaxedIter_ < 0)
256  {
257  FatalIOErrorIn("layerParameters::layerParameters(..)", dict)
258  << "Layer iterations should be >= 0." << endl
259  << "nLayerIter:" << nLayerIter_
260  << " nRelaxedIter:" << nRelaxedIter_
261  << exit(FatalIOError);
262  }
263 
264 
265  const dictionary& layersDict = dict.subDict("layers");
266 
267  forAllConstIter(dictionary, layersDict, iter)
268  {
269  if (iter().isDict())
270  {
271  const keyType& key = iter().keyword();
272  const labelHashSet patchIDs
273  (
274  boundaryMesh.patchSet(List<wordRe>(1, wordRe(key)))
275  );
276 
277  if (patchIDs.size() == 0)
278  {
279  IOWarningIn("layerParameters::layerParameters(..)", layersDict)
280  << "Layer specification for " << key
281  << " does not match any patch." << endl
282  << "Valid patches are " << boundaryMesh.names() << endl;
283  }
284  else
285  {
286  const dictionary& layerDict = iter().dict();
287 
288  forAllConstIter(labelHashSet, patchIDs, patchIter)
289  {
290  label patchI = patchIter.key();
291 
292  numLayers_[patchI] =
293  readLabel(layerDict.lookup("nSurfaceLayers"));
294 
295  switch (layerSpec_)
296  {
297  case FIRST_AND_TOTAL:
298  layerDict.readIfPresent
299  (
300  "firstLayerThickness",
301  firstLayerThickness_[patchI]
302  );
303  layerDict.readIfPresent
304  (
305  "thickness",
306  thickness_[patchI]
307  );
308  break;
309 
310  case FIRST_AND_EXPANSION:
311  layerDict.readIfPresent
312  (
313  "firstLayerThickness",
314  firstLayerThickness_[patchI]
315  );
316  layerDict.readIfPresent
317  (
318  "expansionRatio",
319  expansionRatio_[patchI]
320  );
321  break;
322 
323  case FINAL_AND_TOTAL:
324  layerDict.readIfPresent
325  (
326  "finalLayerThickness",
327  finalLayerThickness_[patchI]
328  );
329  layerDict.readIfPresent
330  (
331  "thickness",
332  thickness_[patchI]
333  );
334  break;
335 
336  case FINAL_AND_EXPANSION:
337  layerDict.readIfPresent
338  (
339  "finalLayerThickness",
340  finalLayerThickness_[patchI]
341  );
342  layerDict.readIfPresent
343  (
344  "expansionRatio",
345  expansionRatio_[patchI]
346  );
347  break;
348 
349  case TOTAL_AND_EXPANSION:
350  layerDict.readIfPresent
351  (
352  "thickness",
353  thickness_[patchI]
354  );
355  layerDict.readIfPresent
356  (
357  "expansionRatio",
358  expansionRatio_[patchI]
359  );
360  break;
361 
362  default:
364  (
365  "layerParameters::layerParameters(..)",
366  dict
367  ) << "problem." << exit(FatalIOError);
368  break;
369  }
370 
371  layerDict.readIfPresent
372  (
373  "minThickness",
374  minThickness_[patchI]
375  );
376  }
377  }
378  }
379  }
380 }
381 
382 
383 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
384 
386 (
387  const label nLayers,
388  const scalar firstLayerThickess,
389  const scalar finalLayerThickess,
390  const scalar totalThickness,
391  const scalar expansionRatio
392 ) const
393 {
394  switch (layerSpec_)
395  {
396  case FIRST_AND_TOTAL:
397  case FINAL_AND_TOTAL:
398  case TOTAL_AND_EXPANSION:
399  {
400  return totalThickness;
401  }
402  break;
403 
404  case FIRST_AND_EXPANSION:
405  {
406  if (mag(expansionRatio-1) < SMALL)
407  {
408  return firstLayerThickess * nLayers;
409  }
410  else
411  {
412  return firstLayerThickess *
413  (1.0 - pow(expansionRatio, nLayers))
414  / (1.0 - expansionRatio);
415  }
416  }
417  break;
418 
419  case FINAL_AND_EXPANSION:
420  {
421  if (mag(expansionRatio-1) < SMALL)
422  {
423  return finalLayerThickess * nLayers;
424  }
425  else
426  {
427  scalar invExpansion = 1.0 / expansionRatio;
428  return finalLayerThickess *
429  (1.0 - pow(invExpansion, nLayers))
430  / (1.0 - invExpansion);
431  }
432  }
433  break;
434 
435  default:
436  {
437  FatalErrorIn("layerParameters::layerThickness(..)")
438  << "Illegal thickness specification " << layerSpec_
439  << exit(FatalError);
440  return -VGREAT;
441  }
442  }
443 }
444 
445 
446 Foam::scalar Foam::layerParameters::layerExpansionRatio
447 (
448  const label nLayers,
449  const scalar firstLayerThickess,
450  const scalar finalLayerThickess,
451  const scalar totalThickness,
452  const scalar expansionRatio
453 ) const
454 {
455  switch (layerSpec_)
456  {
457  case FIRST_AND_EXPANSION:
458  case FINAL_AND_EXPANSION:
459  case TOTAL_AND_EXPANSION:
460  {
461  return expansionRatio;
462  }
463  break;
464 
465  case FIRST_AND_TOTAL:
466  {
467  return layerExpansionRatio
468  (
469  nLayers,
470  totalThickness/firstLayerThickess
471  );
472  }
473  break;
474 
475  case FINAL_AND_TOTAL:
476  {
477  return
478  1.0
479  / layerExpansionRatio
480  (
481  nLayers,
482  totalThickness/finalLayerThickess
483  );
484  }
485  break;
486 
487  default:
488  {
489  FatalErrorIn("layerParameters::layerThickness(..)")
490  << "Illegal thickness specification" << exit(FatalError);
491  return -VGREAT;
492  }
493  }
494 }
495 
496 
498 (
499  const label nLayers,
500  const scalar firstLayerThickess,
501  const scalar finalLayerThickess,
502  const scalar totalThickness,
503  const scalar expansionRatio
504 ) const
505 {
506  switch (layerSpec_)
507  {
508  case FIRST_AND_EXPANSION:
509  case FIRST_AND_TOTAL:
510  {
511  return firstLayerThickess;
512  }
513 
514  case FINAL_AND_EXPANSION:
515  {
516  return finalLayerThickess*pow(1.0/expansionRatio, nLayers-1);
517  }
518  break;
519 
520  case FINAL_AND_TOTAL:
521  {
522  scalar r = layerExpansionRatio
523  (
524  nLayers,
525  firstLayerThickess,
526  finalLayerThickess,
527  totalThickness,
528  expansionRatio
529  );
530  return finalLayerThickess/pow(r, nLayers-1);
531  }
532  break;
533 
534  case TOTAL_AND_EXPANSION:
535  {
536  scalar r = finalLayerThicknessRatio
537  (
538  nLayers,
539  expansionRatio
540  );
541  scalar finalThickness = r*totalThickness;
542  return finalThickness/pow(expansionRatio, nLayers-1);
543  }
544  break;
545 
546  default:
547  {
548  FatalErrorIn("layerParameters::layerThickness(..)")
549  << "Illegal thickness specification" << exit(FatalError);
550  return -VGREAT;
551  }
552  }
553 }
554 
555 
557 (
558  const label nLayers,
559  const scalar expansionRatio
560 ) const
561 {
562  if (nLayers > 0)
563  {
564  if (mag(expansionRatio-1) < SMALL)
565  {
566  return 1.0/nLayers;
567  }
568  else
569  {
570  return
571  pow(expansionRatio, nLayers - 1)
572  * (1.0 - expansionRatio)
573  / (1.0 - pow(expansionRatio, nLayers));
574  }
575  }
576  else
577  {
578  return 0.0;
579  }
580 }
581 
582 
583 // ************************************************************************* //
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:306
label size() const
Return the number of elements in the PtrList.
Definition: PtrListI.H:32
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
dimensioned< scalar > mag(const dimensioned< Type > &)
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
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
scalar layerThickness(const label nLayers, const scalar firstLayerThickess, const scalar finalLayerThickess, const scalar totalThickness, const scalar expansionRatio) const
Determine overall thickness. Uses two of the four parameters.
messageStream Info
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:638
#define IOWarningIn(functionName, ios)
Report an IO warning using Foam::Warning.
const scalarField & expansionRatio() const
label readLabel(Istream &is)
Definition: label.H:64
A class for handling keywords in dictionaries.
Definition: keyType.H:56
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
wordList names() const
Return a list of patch names.
static const char nl
Definition: Ostream.H:260
const double e
Elementary charge.
Definition: doubleFloat.H:78
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
IOerror FatalIOError
Foam::polyBoundaryMesh.
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
Definition: doubleScalar.H:63
Unit conversion functions.
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
labelHashSet patchSet(const UList< wordRe > &patchNames, const bool warnNotFound=true, const bool usePatchGroups=true) const
Return the set of patch IDs corresponding to the given names.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:452
error FatalError
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
scalar finalLayerThicknessRatio(const label nLayers, const scalar expansionRatio) const
Determine ratio of final layer thickness to.
const scalarField & firstLayerThickness() const
Wanted thickness of the layer nearest to the wall.
A wordRe is a word, but can also have a regular expression for matching words.
Definition: wordRe.H:74
#define FatalIOErrorIn(functionName, ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:325
static const label labelMax
Definition: label.H:62