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