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-2021 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::Enum
39 <
41 >
42 Foam::layerParameters::thicknessModelTypeNames_
43 ({
44  { thicknessModelType::FIRST_AND_TOTAL, "firstAndOverall" },
45  { thicknessModelType::FIRST_AND_EXPANSION, "firstAndExpansion" },
46  { thicknessModelType::FINAL_AND_TOTAL, "finalAndOverall" },
47  { thicknessModelType::FINAL_AND_EXPANSION, "finalAndExpansion" },
48  { thicknessModelType::TOTAL_AND_EXPANSION, "overallAndExpansion" },
49  { thicknessModelType::FIRST_AND_RELATIVE_FINAL, "firstAndRelativeFinal" },
50 });
51 
52 const Foam::scalar Foam::layerParameters::defaultConcaveAngle = 90;
53 
54 
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 
57 Foam::scalar Foam::layerParameters::layerExpansionRatio
58 (
59  const label n,
60  const scalar totalOverFirst
61 )
62 {
63  if (n <= 1)
64  {
65  return 1.0;
66  }
67 
68  const label maxIters = 20;
69  const scalar tol = 1e-8;
70 
71  if (mag(n-totalOverFirst) < tol)
72  {
73  return 1.0;
74  }
75 
76  // Calculate the bounds of the solution
77  scalar minR;
78  scalar maxR;
79 
80  if (totalOverFirst < n)
81  {
82  minR = 0.0;
83  maxR = pow(totalOverFirst/n, scalar(1)/(n-1));
84  }
85  else
86  {
87  minR = pow(totalOverFirst/n, scalar(1)/(n-1));
88  maxR = totalOverFirst/(n - 1);
89  }
90 
91  // Starting guess
92  scalar r = 0.5*(minR + maxR);
93 
94  for (label i = 0; i < maxIters; ++i)
95  {
96  const scalar prevr = r;
97 
98  const scalar fx = pow(r, n) - totalOverFirst*r - (1 - totalOverFirst);
99  const scalar dfx = n*pow(r, n - 1) - totalOverFirst;
100  r -= fx/dfx;
101 
102  if (mag(r - prevr) < tol)
103  {
104  break;
105  }
106  }
107  return r;
108 }
109 
110 
111 void Foam::layerParameters::readLayerParameters
112 (
113  const bool verbose,
114  const dictionary& dict,
115  const thicknessModelType& spec,
116  scalar& firstLayerThickness,
117  scalar& finalLayerThickness,
118  scalar& thickness,
119  scalar& expansionRatio
120 )
121 {
122  // Now we have determined the layer-specification read the actual fields
123  switch (spec)
124  {
125  case FIRST_AND_TOTAL:
126  if (verbose)
127  {
128  Info<< "Layer specification as" << nl
129  << "- first layer thickness ('firstLayerThickness')" << nl
130  << "- overall thickness ('thickness')" << endl;
131  }
132  firstLayerThickness = dict.get<scalar>("firstLayerThickness");
133  thickness = dict.get<scalar>("thickness");
134  break;
135 
136  case FIRST_AND_EXPANSION:
137  if (verbose)
138  {
139  Info<< "Layer specification as" << nl
140  << "- first layer thickness ('firstLayerThickness')" << nl
141  << "- expansion ratio ('expansionRatio')" << endl;
142  }
143  firstLayerThickness = dict.get<scalar>("firstLayerThickness");
144  expansionRatio = dict.get<scalar>("expansionRatio");
145  break;
146 
147  case FINAL_AND_TOTAL:
148  if (verbose)
149  {
150  Info<< "Layer specification as" << nl
151  << "- final layer thickness ('finalLayerThickness')" << nl
152  << "- overall thickness ('thickness')" << endl;
153  }
154  finalLayerThickness = dict.get<scalar>("finalLayerThickness");
155  thickness = dict.get<scalar>("thickness");
156  break;
157 
158  case FINAL_AND_EXPANSION:
159  if (verbose)
160  {
161  Info<< "Layer specification as" << nl
162  << "- final layer thickness ('finalLayerThickness')" << nl
163  << "- expansion ratio ('expansionRatio')" << endl;
164  }
165  finalLayerThickness = dict.get<scalar>("finalLayerThickness");
166  expansionRatio = dict.get<scalar>("expansionRatio");
167  break;
168 
169  case TOTAL_AND_EXPANSION:
170  if (verbose)
171  {
172  Info<< "Layer specification as" << nl
173  << "- overall thickness ('thickness')" << nl
174  << "- expansion ratio ('expansionRatio')" << endl;
175  }
176  thickness = dict.get<scalar>("thickness");
177  expansionRatio = dict.get<scalar>("expansionRatio");
178  break;
179 
180  case FIRST_AND_RELATIVE_FINAL:
181  if (verbose)
182  {
183  Info<< "Layer specification as" << nl
184  << "- absolute first layer thickness"
185  << " ('firstLayerThickness')"
186  << nl
187  << "- and final layer thickness"
188  << " ('finalLayerThickness')" << nl
189  << endl;
190  }
191  firstLayerThickness = dict.get<scalar>("firstLayerThickness");
192  finalLayerThickness = dict.get<scalar>("finalLayerThickness");
193  break;
194 
195  default:
197  << "problem." << exit(FatalIOError);
198  break;
199  }
200 }
201 
202 
203 void Foam::layerParameters::calculateLayerParameters
204 (
205  const thicknessModelType& spec,
206  const label nLayers,
207  scalar& firstThickness,
208  scalar& finalThickness,
209  scalar& thickness,
210  scalar& expansionRatio
211 )
212 {
213  // Calculate the non-read parameters
214  switch (spec)
215  {
216  case FIRST_AND_TOTAL:
217  expansionRatio = layerExpansionRatio
218  (
219  spec,
220  nLayers,
221  firstThickness,
222  VGREAT,
223  thickness, //totalThickness
224  VGREAT //expansionRatio
225  );
226  finalThickness =
227  thickness
228  *finalLayerThicknessRatio(nLayers, expansionRatio);
229 
230  break;
231 
232  case FIRST_AND_EXPANSION:
233  thickness = layerThickness
234  (
235  spec,
236  nLayers,
237  firstThickness, //firstThickness
238  VGREAT, //finalThickness
239  VGREAT, //totalThickness
240  expansionRatio //expansionRatio
241  );
242  finalThickness =
243  thickness
244  *finalLayerThicknessRatio(nLayers, expansionRatio);
245 
246  break;
247 
248  case FINAL_AND_TOTAL:
249  firstThickness = firstLayerThickness
250  (
251  spec,
252  nLayers,
253  VGREAT, //firstThickness
254  VGREAT, //finalThickness
255  thickness, //totalThickness
256  VGREAT //expansionRatio
257  );
258  expansionRatio = layerExpansionRatio
259  (
260  spec,
261  nLayers,
262  VGREAT, //firstThickness
263  finalThickness, //finalThickness
264  thickness, //totalThickness
265  VGREAT //expansionRatio
266  );
267 
268  break;
269 
270  case FINAL_AND_EXPANSION:
271  firstThickness = firstLayerThickness
272  (
273  spec,
274  nLayers,
275  VGREAT, //firstThickness
276  finalThickness, //finalThickness
277  VGREAT, //thickness
278  expansionRatio //expansionRatio
279  );
280  thickness = layerThickness
281  (
282  spec,
283  nLayers,
284  VGREAT, //firstThickness
285  finalThickness, //finalThickness
286  VGREAT, //totalThickness
287  expansionRatio //expansionRatio
288  );
289  break;
290 
291  case TOTAL_AND_EXPANSION:
292  firstThickness = firstLayerThickness
293  (
294  spec,
295  nLayers,
296  VGREAT, //firstThickness
297  finalThickness, //finalThickness
298  VGREAT, //thickness
299  expansionRatio //expansionRatio
300  );
301  finalThickness =
302  thickness
303  *finalLayerThicknessRatio(nLayers, expansionRatio);
304 
305  break;
306 
307  case FIRST_AND_RELATIVE_FINAL:
308  thickness = layerThickness
309  (
310  spec,
311  nLayers,
312  firstThickness, //firstThickness
313  finalThickness, //finalThickness
314  VGREAT, //totalThickness
315  VGREAT //expansionRatio
316  );
317  expansionRatio = layerExpansionRatio
318  (
319  spec,
320  nLayers,
321  firstThickness, //firstThickness
322  finalThickness, //finalThickness
323  VGREAT, //totalThickness
324  VGREAT //expansionRatio
325  );
326 
327  break;
328 
329  default:
330  FatalErrorInFunction << "Illegal thicknessModel " << spec
331  << exit(FatalError);
332  break;
333  }
334 }
335 
336 
337 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
338 
339 Foam::layerParameters::layerParameters
340 (
341  const dictionary& dict,
342  const polyBoundaryMesh& boundaryMesh,
343  const bool dryRun
344 )
345 :
346  dict_(dict),
347  dryRun_(dryRun),
348  numLayers_(boundaryMesh.size(), -1),
349  relativeSizes_
350  (
351  boundaryMesh.size(),
352  meshRefinement::get<bool>(dict, "relativeSizes", dryRun)
353  ),
354  layerModels_(boundaryMesh.size(), FIRST_AND_TOTAL),
355  firstLayerThickness_(boundaryMesh.size(), -123),
356  finalLayerThickness_(boundaryMesh.size(), -123),
357  thickness_(boundaryMesh.size(), -123),
358  expansionRatio_(boundaryMesh.size(), -123),
359  minThickness_
360  (
361  boundaryMesh.size(),
362  meshRefinement::get<scalar>(dict, "minThickness", dryRun)
363  ),
364  featureAngle_(meshRefinement::get<scalar>(dict, "featureAngle", dryRun)),
365  mergePatchFacesAngle_
366  (
367  dict.getOrDefault<scalar>
368  (
369  "mergePatchFacesAngle",
370  featureAngle_
371  )
372  ),
373  concaveAngle_
374  (
375  dict.getOrDefault<scalar>("concaveAngle", defaultConcaveAngle)
376  ),
377  nGrow_(meshRefinement::get<label>(dict, "nGrow", dryRun)),
378  maxFaceThicknessRatio_
379  (
380  meshRefinement::get<scalar>(dict, "maxFaceThicknessRatio", dryRun)
381  ),
382  nBufferCellsNoExtrude_
383  (
384  meshRefinement::get<label>(dict, "nBufferCellsNoExtrude", dryRun)
385  ),
386  nLayerIter_(meshRefinement::get<label>(dict, "nLayerIter", dryRun)),
387  nRelaxedIter_(labelMax),
388  additionalReporting_(dict.getOrDefault("additionalReporting", false)),
389  meshShrinker_
390  (
391  dict.getOrDefault
392  (
393  "meshShrinker",
394  medialAxisMeshMover::typeName
395  )
396  ),
397  nOuterIter_(dict.getOrDefault<scalar>("nOuterIter", 1))
398 {
399  // Detect layer specification mode
400 
401  word spec;
402  if (dict.readIfPresent("thicknessModel", spec))
403  {
404  layerModels_ = thicknessModelTypeNames_[spec];
405  }
406  else
407  {
408  // Count number of specifications
409  label nSpec = 0;
410 
411  bool haveFirst = dict.found("firstLayerThickness");
412  if (haveFirst)
413  {
414  nSpec++;
415  }
416  bool haveFinal = dict.found("finalLayerThickness");
417  if (haveFinal)
418  {
419  nSpec++;
420  }
421  bool haveTotal = dict.found("thickness");
422  if (haveTotal)
423  {
424  nSpec++;
425  }
426  bool haveExp = dict.found("expansionRatio");
427  if (haveExp)
428  {
429  nSpec++;
430  }
431 
432  if (nSpec == 2 && haveFirst && haveTotal)
433  {
434  layerModels_ = FIRST_AND_TOTAL;
435  //Info<< "Layer thickness specified as first layer"
436  // << " and overall thickness." << endl;
437  }
438  else if (nSpec == 2 && haveFirst && haveExp)
439  {
440  layerModels_ = FIRST_AND_EXPANSION;
441  //Info<< "Layer thickness specified as first layer"
442  // << " and expansion ratio." << endl;
443  }
444  else if (nSpec == 2 && haveFinal && haveTotal)
445  {
446  layerModels_ = FINAL_AND_TOTAL;
447  //Info<< "Layer thickness specified as final layer"
448  // << " and overall thickness." << endl;
449  }
450  else if (nSpec == 2 && haveFinal && haveExp)
451  {
452  layerModels_ = FINAL_AND_EXPANSION;
453  //Info<< "Layer thickness specified as final layer"
454  // << " and expansion ratio." << endl;
455  }
456  else if (nSpec == 2 && haveTotal && haveExp)
457  {
458  layerModels_ = TOTAL_AND_EXPANSION;
459  //Info<< "Layer thickness specified as overall thickness"
460  // << " and expansion ratio." << endl;
461  }
462  else if (nSpec == 2 && haveFirst && haveFinal)
463  {
464  layerModels_ = FIRST_AND_RELATIVE_FINAL;
465  //Info<< "Layer thickness specified as absolute first and"
466  // << " relative final layer ratio." << endl;
467  }
468  else
469  {
471  << "Over- or underspecified layer thickness."
472  << " Please specify" << nl
473  << " first layer thickness ('firstLayerThickness')"
474  << " and overall thickness ('thickness') or" << nl
475  << " first layer thickness ('firstLayerThickness')"
476  << " and expansion ratio ('expansionRatio') or" << nl
477  << " final layer thickness ('finalLayerThickness')"
478  << " and expansion ratio ('expansionRatio') or" << nl
479  << " final layer thickness ('finalLayerThickness')"
480  << " and overall thickness ('thickness') or" << nl
481  << " overall thickness ('thickness')"
482  << " and expansion ratio ('expansionRatio'"
483  << exit(FatalIOError);
484  }
485  }
486 
487 
488  // Now we have determined the layer-specification read the actual fields
489  scalar firstThickness;
490  scalar finalThickness;
491  scalar thickness;
492  scalar expansionRatio;
493  readLayerParameters
494  (
495  true, // verbose
496  dict,
497  layerModels_[0], // spec
498  firstThickness,
499  finalThickness,
500  thickness,
502  );
503  firstLayerThickness_ = firstThickness;
504  finalLayerThickness_ = finalThickness;
505  thickness_ = thickness;
506  expansionRatio_ = expansionRatio;
507 
508  dict.readIfPresent("nRelaxedIter", nRelaxedIter_);
509 
510  if (nLayerIter_ < 0 || nRelaxedIter_ < 0)
511  {
513  << "Layer iterations should be >= 0." << nl
514  << "nLayerIter:" << nLayerIter_
515  << " nRelaxedIter:" << nRelaxedIter_
516  << exit(FatalIOError);
517  }
518 
519 
520  const dictionary& layersDict = meshRefinement::subDict
521  (
522  dict,
523  "layers",
524  dryRun
525  );
526 
527  for (const entry& dEntry : layersDict)
528  {
529  if (dEntry.isDict())
530  {
531  const keyType& key = dEntry.keyword();
532  const dictionary& layerDict = dEntry.dict();
533 
534  const labelHashSet patchIDs
535  (
536  boundaryMesh.patchSet(wordRes(one{}, wordRe(key)))
537  );
538 
539  if (patchIDs.size() == 0)
540  {
541  IOWarningInFunction(layersDict)
542  << "Layer specification for " << key
543  << " does not match any patch." << endl
544  << "Valid patches are " << boundaryMesh.names() << endl;
545  }
546  else
547  {
548  for (const label patchi : patchIDs)
549  {
550  numLayers_[patchi] =
551  layerDict.get<label>("nSurfaceLayers");
552 
553  word spec;
554  if (layerDict.readIfPresent("thicknessModel", spec))
555  {
556  // If the thickness model is explicitly specified
557  // we want full specification of all parameters
558  layerModels_[patchi] = thicknessModelTypeNames_[spec];
559  readLayerParameters
560  (
561  false, // verbose
562  layerDict,
563  layerModels_[patchi], // spec
564  firstLayerThickness_[patchi],
565  finalLayerThickness_[patchi],
566  thickness_[patchi],
567  expansionRatio_[patchi]
568  );
569  minThickness_[patchi] =
570  layerDict.get<scalar>("minThickness");
571  }
572  else
573  {
574  // Optional override of thickness parameters
575  switch (layerModels_[patchi])
576  {
577  case FIRST_AND_TOTAL:
578  layerDict.readIfPresent
579  (
580  "firstLayerThickness",
581  firstLayerThickness_[patchi]
582  );
583  layerDict.readIfPresent
584  (
585  "thickness",
586  thickness_[patchi]
587  );
588  break;
589 
590  case FIRST_AND_EXPANSION:
591  layerDict.readIfPresent
592  (
593  "firstLayerThickness",
594  firstLayerThickness_[patchi]
595  );
596  layerDict.readIfPresent
597  (
598  "expansionRatio",
599  expansionRatio_[patchi]
600  );
601  break;
602 
603  case FINAL_AND_TOTAL:
604  layerDict.readIfPresent
605  (
606  "finalLayerThickness",
607  finalLayerThickness_[patchi]
608  );
609  layerDict.readIfPresent
610  (
611  "thickness",
612  thickness_[patchi]
613  );
614  break;
615 
616  case FINAL_AND_EXPANSION:
617  layerDict.readIfPresent
618  (
619  "finalLayerThickness",
620  finalLayerThickness_[patchi]
621  );
622  layerDict.readIfPresent
623  (
624  "expansionRatio",
625  expansionRatio_[patchi]
626  );
627  break;
628 
629  case TOTAL_AND_EXPANSION:
630  layerDict.readIfPresent
631  (
632  "thickness",
633  thickness_[patchi]
634  );
635  layerDict.readIfPresent
636  (
637  "expansionRatio",
638  expansionRatio_[patchi]
639  );
640  break;
641 
643  layerDict.readIfPresent
644  (
645  "firstLayerThickness",
646  firstLayerThickness_[patchi]
647  );
648  layerDict.readIfPresent
649  (
650  "finalLayerThickness",
651  finalLayerThickness_[patchi]
652  );
653  break;
654 
655  default:
657  << "problem." << exit(FatalIOError);
658  break;
659  }
660 
661  layerDict.readIfPresent
662  (
663  "minThickness",
664  minThickness_[patchi]
665  );
666  }
667 
668  layerDict.readIfPresent
669  (
670  "relativeSizes",
671  relativeSizes_[patchi]
672  );
673  }
674  }
675  }
676  }
677 
678 
679  forAll(numLayers_, patchi)
680  {
681  // Calculate the remaining parameters
682  calculateLayerParameters
683  (
684  layerModels_[patchi],
685  numLayers_[patchi],
686  firstLayerThickness_[patchi],
687  finalLayerThickness_[patchi],
688  thickness_[patchi],
689  expansionRatio_[patchi]
690  );
691  }
692 }
693 
694 
695 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
696 
698 (
699  const label nLayers,
700  const scalar layerThickness, // overall layer thickness
701  const scalar expansionRatio,
702 
703  const label layerStart, // start in nLayers
704  const label layerSize // size of slice of nLayers
705 )
706 {
707  if (layerSize == 0 || nLayers == 0)
708  {
709  return 0.0;
710  }
711  else if (layerSize > nLayers || layerStart >= nLayers)
712  {
713  FatalErrorInFunction << "Illegal input for slice of layer:"
714  << " overall nLayers:" << nLayers
715  << " slice nLayers:" << layerSize
716  << " slice start:" << layerStart
717  << exit(FatalError);
718  return 0.0;
719  }
720  else if (mag(expansionRatio-1) < SMALL)
721  {
722  return layerThickness*layerSize/nLayers;
723  }
724  else
725  {
726  const scalar firstLayerThickness =
727  finalLayerThicknessRatio(nLayers, expansionRatio)
728  * layerThickness
729  / pow(expansionRatio, nLayers-1);
730 
731  // Calculate thickness of single layer at layerStart
732  const scalar startThickness =
733  firstLayerThickness
734  *pow(expansionRatio, layerStart);
735 
736  // See below for formula
737  const scalar thickness =
738  startThickness
739  *(1.0 - pow(expansionRatio, layerSize))
740  /(1.0 - expansionRatio);
742  return thickness;
743  }
744 }
745 
746 
748 (
749  const thicknessModelType layerSpec,
750  const label nLayers,
751  const scalar firstLayerThickness,
752  const scalar finalLayerThickness,
753  const scalar totalThickness,
754  const scalar expansionRatio
755 )
756 {
757  switch (layerSpec)
758  {
759  case FIRST_AND_TOTAL:
760  case FINAL_AND_TOTAL:
761  case TOTAL_AND_EXPANSION:
762  {
763  return totalThickness;
764  }
765  break;
766 
767  case FIRST_AND_EXPANSION:
768  {
769  if (mag(expansionRatio-1) < SMALL)
770  {
771  return firstLayerThickness * nLayers;
772  }
773  else
774  {
775  return firstLayerThickness
776  *(1.0 - pow(expansionRatio, nLayers))
777  /(1.0 - expansionRatio);
778  }
779  }
780  break;
781 
782  case FINAL_AND_EXPANSION:
783  {
784  if (mag(expansionRatio-1) < SMALL)
785  {
786  return finalLayerThickness * nLayers;
787  }
788  else
789  {
790  scalar invExpansion = 1.0 / expansionRatio;
791  return finalLayerThickness
792  *(1.0 - pow(invExpansion, nLayers))
793  /(1.0 - invExpansion);
794  }
795  }
796  break;
797 
798  case FIRST_AND_RELATIVE_FINAL:
799  {
800  if (mag(expansionRatio-1) < SMALL)
801  {
802  return firstLayerThickness * nLayers;
803  }
804  else
805  {
806  scalar ratio = layerExpansionRatio
807  (
808  layerSpec,
809  nLayers,
810  firstLayerThickness,
811  finalLayerThickness,
812  totalThickness,
813  expansionRatio
814  );
815 
816  if (mag(ratio-1) < SMALL)
817  {
818  return firstLayerThickness * nLayers;
819  }
820  else
821  {
822  return firstLayerThickness *
823  (1.0 - pow(ratio, nLayers))
824  / (1.0 - ratio);
825  }
826  }
827  }
828  break;
829 
830  default:
831  {
833  << layerSpec << exit(FatalError);
834  return -VGREAT;
835  }
836  }
837 }
838 
839 
840 Foam::scalar Foam::layerParameters::layerExpansionRatio
841 (
842  const thicknessModelType layerSpec,
843  const label nLayers,
844  const scalar firstLayerThickness,
845  const scalar finalLayerThickness,
846  const scalar totalThickness,
847  const scalar expansionRatio
848 )
849 {
850  switch (layerSpec)
851  {
852  case FIRST_AND_EXPANSION:
853  case FINAL_AND_EXPANSION:
854  case TOTAL_AND_EXPANSION:
855  {
856  return expansionRatio;
857  }
858  break;
859 
860  case FIRST_AND_TOTAL:
861  {
862  if (firstLayerThickness < SMALL)
863  {
864  // Do what?
865  return 1;
866  }
867  else
868  {
869  return layerExpansionRatio
870  (
871  nLayers,
872  totalThickness/firstLayerThickness
873  );
874  }
875  }
876  break;
877 
878  case FINAL_AND_TOTAL:
879  {
880  if (finalLayerThickness < SMALL)
881  {
882  // Do what?
883  return 1;
884  }
885  else
886  {
887  return
888  1.0
889  / layerExpansionRatio
890  (
891  nLayers,
892  totalThickness/finalLayerThickness
893  );
894  }
895  }
896  break;
897 
898  case FIRST_AND_RELATIVE_FINAL:
899  {
900  if (firstLayerThickness < SMALL || nLayers <= 1)
901  {
902  return 1.0;
903  }
904  else
905  {
906  // Note: at this point the finalLayerThickness is already
907  // absolute
908  return pow
909  (
910  finalLayerThickness/firstLayerThickness,
911  1.0/(nLayers-1)
912  );
913  }
914  }
915  break;
916 
917  default:
918  {
920  << "Illegal thickness specification" << exit(FatalError);
921  return -VGREAT;
922  }
923  }
924 }
925 
926 
928 (
929  const thicknessModelType layerSpec,
930  const label nLayers,
931  const scalar firstLayerThickness,
932  const scalar finalLayerThickness,
933  const scalar totalThickness,
934  const scalar expansionRatio
935 )
936 {
937  switch (layerSpec)
938  {
939  case FIRST_AND_EXPANSION:
940  case FIRST_AND_TOTAL:
941  case FIRST_AND_RELATIVE_FINAL:
942  {
943  return firstLayerThickness;
944  }
945 
946  case FINAL_AND_EXPANSION:
947  {
948  if (expansionRatio < SMALL)
949  {
950  // Do what?
951  return 0.0;
952  }
953  else
954  {
955  return finalLayerThickness*pow(1.0/expansionRatio, nLayers-1);
956  }
957  }
958  break;
959 
960  case FINAL_AND_TOTAL:
961  {
962  scalar r = layerExpansionRatio
963  (
964  layerSpec,
965  nLayers,
966  firstLayerThickness,
967  finalLayerThickness,
968  totalThickness,
969  expansionRatio
970  );
971  return finalLayerThickness/pow(r, nLayers-1);
972  }
973  break;
974 
975  case TOTAL_AND_EXPANSION:
976  {
977  scalar r = finalLayerThicknessRatio
978  (
979  nLayers,
980  expansionRatio
981  );
982  scalar finalThickness = r*totalThickness;
983  return finalThickness/pow(expansionRatio, nLayers-1);
984  }
985  break;
986 
987  default:
988  {
990  << "Illegal thickness specification" << exit(FatalError);
991  return -VGREAT;
992  }
993  }
994 }
995 
996 
998 (
999  const label nLayers,
1000  const scalar expansionRatio
1001 )
1002 {
1003  if (nLayers > 0)
1004  {
1005  if (mag(expansionRatio-1) < SMALL)
1006  {
1007  return 1.0/nLayers;
1008  }
1009  else
1010  {
1011  return
1012  pow(expansionRatio, nLayers - 1)
1013  *(1.0 - expansionRatio)
1014  /(1.0 - pow(expansionRatio, nLayers));
1015  }
1016  }
1017  else
1018  {
1019  return 0.0;
1020  }
1021 }
1022 
1023 
1024 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
const labelList patchIDs(pbm.indices(polyPatchNames, true))
dictionary dict
static const dictionary & subDict(const dictionary &dict, const word &keyword, const bool noExit, enum keyType::option matchOpt=keyType::REGEX)
Wrapper around dictionary::subDict which does not exit.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
Unit conversion functions.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type get(const label i) const
Return bool value at specified position, always false for out-of-range access.
Definition: UList.H:782
const dictionary & dict() const
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:104
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
const scalarField & firstLayerThickness() const
Wanted thickness of the layer nearest to the wall.
static scalar finalLayerThicknessRatio(const label nLayers, const scalar expansionRatio)
Determine ratio of final layer thickness to.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
const scalarField & expansionRatio() const
const scalarField & thickness() const
Wanted overall thickness of all layers.
thicknessModelType
Enumeration defining the layer specification:
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: error.H:64
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
static scalar layerThickness(const thicknessModelType, const label nLayers, const scalar firstLayerThickness, const scalar finalLayerThickness, const scalar totalThickness, const scalar expansionRatio)
Determine overall thickness. Uses two of the four parameters.
messageStream Info
Information stream (stdout output on master, null elsewhere)
constexpr label labelMax
Definition: label.H:55
label n
static constexpr int maxIters
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...