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