highAspectRatioFvGeometryScheme.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) 2020 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
30 #include "fvMesh.H"
31 #include "syncTools.H"
32 #include "cellAspectRatio.H"
33 #include "emptyPolyPatch.H"
34 #include "wedgePolyPatch.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40  defineTypeNameAndDebug(highAspectRatioFvGeometryScheme, 0);
42  (
43  fvGeometryScheme,
44  highAspectRatioFvGeometryScheme,
45  dict
46  );
47 }
48 
49 
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
51 
52 //void Foam::highAspectRatioFvGeometryScheme::cellClosedness
53 //(
54 // const vectorField& areas,
55 // const scalarField& vols,
56 // const tensorField& cellCoords,
57 //
58 // scalarField& aratio
59 //) const
60 //{
61 // // From primitiveMeshTools::cellClosedness:
62 // // calculate aspect ratio in given direction
63 // const labelList& own = mesh_.faceOwner();
64 // const labelList& nei = mesh_.faceNeighbour();
65 //
66 // // Loop through cell faces and sum up the face area vectors for each cell.
67 // // This should be zero in all vector components
68 //
69 // vectorField sumMagClosed(mesh_.nCells(), Zero);
70 //
71 // forAll(own, facei)
72 // {
73 // // Add to owner
74 // vector& v = sumMagClosed[own[facei]];
75 // v += cmptMag(cellCoords[own[facei]] & areas[facei]);
76 // }
77 //
78 // forAll(nei, facei)
79 // {
80 // // Subtract from neighbour
81 // vector& v = sumMagClosed[nei[facei]];
82 // v += cmptMag(cellCoords[nei[facei]] & areas[facei]);
83 // }
84 //
85 // // Check the sums
86 // aratio.setSize(mesh_.nCells());
87 //
88 // forAll(sumMagClosed, celli)
89 // {
90 // // Calculate the aspect ration as the maximum of Cartesian component
91 // // aspect ratio to the total area hydraulic area aspect ratio
92 // scalar minCmpt = VGREAT;
93 // scalar maxCmpt = -VGREAT;
94 // for (direction dir = 0; dir < vector::nComponents; dir++)
95 // {
96 // minCmpt = min(minCmpt, sumMagClosed[celli][dir]);
97 // maxCmpt = max(maxCmpt, sumMagClosed[celli][dir]);
98 // }
99 //
100 // scalar aspectRatio = maxCmpt/(minCmpt + ROOTVSMALL);
101 // const scalar v = max(ROOTVSMALL, vols[celli]);
102 //
103 // aspectRatio = max
104 // (
105 // aspectRatio,
106 // 1.0/6.0*cmptSum(sumMagClosed[celli])/Foam::pow(v, 2.0/3.0)
107 // );
108 //
109 // aratio[celli] = aspectRatio;
110 // }
111 //}
112 //
113 //
114 //void Foam::highAspectRatioFvGeometryScheme::cellDirections
115 //(
116 // tensorField& T,
117 // vectorField& lambda
118 //) const
119 //{
120 // // Calculate principal directions in increasing order
121 //
122 // T.setSize(mesh_.nCells());
123 // lambda.setSize(mesh_.nCells());
124 //
125 // forAll(T, celli)
126 // {
127 // tensor J = Zero;
128 // {
129 // const List<tetIndices> cellTets
130 // (
131 // polyMeshTetDecomposition::cellTetIndices
132 // (
133 // mesh_,
134 // celli
135 // )
136 // );
137 // triFaceList faces(cellTets.size());
138 // forAll(cellTets, cTI)
139 // {
140 // faces[cTI] = cellTets[cTI].faceTriIs(mesh_);
141 // }
142 //
143 // scalar m = 0.0;
144 // vector cM = Zero;
145 // J = Zero;
146 // momentOfInertia::massPropertiesShell
147 // (
148 // mesh_.points(),
149 // faces,
150 // 1.0,
151 // m,
152 // cM,
153 // J
154 // );
155 // }
156 //
157 // lambda[celli] = Foam::eigenValues(J);
158 // T[celli] = Foam::eigenVectors(J, lambda[celli]);
159 // }
160 //}
161 
163 (
164  scalarField& cellWeight,
165  scalarField& faceWeight
166 ) const
167 {
168  //scalarField aratio;
169  //{
170  // tensorField principalDirections;
171  // vectorField lambdas;
172  // cellDirections(principalDirections, lambdas);
173  //
174  // cellClosedness
175  // (
176  // mesh_.faceAreas(),
177  // mesh_.cellVolumes(),
178  // principalDirections,
179  // aratio
180  // );
181  //}
182  const cellAspectRatio aratio(mesh_);
183 
184  // Weighting for correction
185  // - 0 if aratio < minAspect_
186  // - 1 if aratio >= maxAspect_
187 
188  scalar delta(maxAspect_-minAspect_);
189  if (delta < ROOTVSMALL)
190  {
191  delta = SMALL;
192  }
193 
194  cellWeight =
195  max
196  (
197  scalar(0),
198  min
199  (
200  scalar(1),
201  (aratio-minAspect_)/delta
202  )
203  );
204 
205  faceWeight.setSize(mesh_.nFaces());
206 
207  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
208  {
209  const label own = mesh_.faceOwner()[facei];
210  const label nei = mesh_.faceNeighbour()[facei];
211  faceWeight[facei] = max(cellWeight[own], cellWeight[nei]);
212  }
213  scalarField nbrCellWeight;
214  syncTools::swapBoundaryCellList
215  (
216  mesh_,
217  cellWeight,
218  nbrCellWeight
219  );
220  for
221  (
222  label facei = mesh_.nInternalFaces();
223  facei < mesh_.nFaces();
224  facei++
225  )
226  {
227  const label own = mesh_.faceOwner()[facei];
228  const label bFacei = facei-mesh_.nInternalFaces();
229  faceWeight[facei] = max(cellWeight[own], nbrCellWeight[bFacei]);
230  }
231 }
232 
233 
235 (
236  const polyMesh& mesh,
237  const pointField& p,
238  const pointField& faceAreas,
239  const scalarField& magFaceAreas,
240  pointField& faceCentres,
241  pointField& cellCentres
242 )
243 {
244  if (debug)
245  {
246  Pout<< "highAspectRatioFvGeometryScheme::makeAverageCentres() : "
247  << "calculating weighted average face/cell centre" << endl;
248  }
249 
250  typedef Vector<solveScalar> solveVector;
251 
252  const faceList& fs = mesh.faces();
253 
254  // Start off from primitiveMesh faceCentres (preserved for triangles)
255  faceCentres.setSize(mesh.nFaces());
256 
257  forAll(fs, facei)
258  {
259  const labelList& f = fs[facei];
260  const label nPoints = f.size();
261 
262  if (nPoints == 3)
263  {
264  faceCentres[facei] = (1.0/3.0)*(p[f[0]] + p[f[1]] + p[f[2]]);
265  }
266  else
267  {
268  solveScalar sumA = 0.0;
269  solveVector sumAc = Zero;
270 
271  for (label pi = 0; pi < nPoints; pi++)
272  {
273  const label nextPi(pi == nPoints-1 ? 0 : pi+1);
274  const solveVector nextPoint(p[f[nextPi]]);
275  const solveVector thisPoint(p[f[pi]]);
276 
277  const solveVector eMid = 0.5*(thisPoint+nextPoint);
278  const solveScalar a = mag(nextPoint-thisPoint);
279 
280  sumAc += a*eMid;
281  sumA += a;
282  }
283  // This is to deal with zero-area faces. Mark very small faces
284  // to be detected in e.g. processorPolyPatch.
285  if (sumA >= ROOTVSMALL)
286  {
287  faceCentres[facei] = sumAc/sumA;
288  }
289  else
290  {
291  // Unweighted average of points
292  sumAc = Zero;
293  for (label pi = 0; pi < nPoints; pi++)
294  {
295  sumAc += static_cast<solveVector>(p[f[pi]]);
296  }
297  faceCentres[facei] = sumAc/nPoints;
298  }
299  }
300  }
301 
302 
303  cellCentres.setSize(mesh.nCells());
304  cellCentres = Zero;
305  {
306  const labelList& own = mesh.faceOwner();
307  const labelList& nei = mesh.faceNeighbour();
308 
309  Field<solveScalar> cellWeights(mesh.nCells(), Zero);
310  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
311  {
312  const solveScalar magfA(magFaceAreas[facei]);
313  const vector weightedFc(magfA*faceCentres[facei]);
314 
315  // Accumulate area-weighted face-centre
316  cellCentres[own[facei]] += weightedFc;
317  cellCentres[nei[facei]] += weightedFc;
318 
319  // Accumulate weights
320  cellWeights[own[facei]] += magfA;
321  cellWeights[nei[facei]] += magfA;
322  }
323 
324  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
325  for (const polyPatch& pp : pbm)
326  {
327  if (!isA<emptyPolyPatch>(pp) && !isA<wedgePolyPatch>(pp))
328  {
329  for
330  (
331  label facei = pp.start();
332  facei < pp.start()+pp.size();
333  facei++
334  )
335  {
336  const solveScalar magfA(magFaceAreas[facei]);
337  const vector weightedFc(magfA*faceCentres[facei]);
338 
339  cellCentres[own[facei]] += weightedFc;
340  cellWeights[own[facei]] += magfA;
341  }
342  }
343  }
344 
345  forAll(cellCentres, celli)
346  {
347  if (mag(cellWeights[celli]) > VSMALL)
348  {
349  cellCentres[celli] /= cellWeights[celli];
350  }
351  }
352  }
353 }
354 
355 
356 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
357 
358 Foam::highAspectRatioFvGeometryScheme::highAspectRatioFvGeometryScheme
359 (
360  const fvMesh& mesh,
361  const dictionary& dict
362 )
363 :
365  minAspect_(dict.get<scalar>("minAspect")),
366  maxAspect_(dict.get<scalar>("maxAspect"))
367 {
368  if (maxAspect_ < minAspect_)
369  {
371  << "minAspect " << minAspect_
372  << " has to be less than maxAspect " << maxAspect_
373  << exit(FatalIOError);
374  }
375  if (minAspect_ < 0 || maxAspect_ < 0)
376  {
378  << "Illegal aspect ratio : minAspect:" << minAspect_
379  << " maxAspect:" << maxAspect_
380  << exit(FatalIOError);
381  }
382 
383  // Force local calculation
384  movePoints();
385 }
386 
387 
388 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
389 
391 {
392  if (debug)
393  {
394  Pout<< "highAspectRatioFvGeometryScheme::movePoints() : "
395  << "recalculating primitiveMesh centres" << endl;
396  }
397 
398  if
399  (
401  && !mesh_.hasFaceCentres()
402  && !mesh_.hasCellVolumes()
403  && !mesh_.hasFaceAreas()
404  )
405  {
406  // Use lower level to calculate the geometry
407  const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
408 
409  pointField avgFaceCentres;
410  pointField avgCellCentres;
412  (
413  mesh_,
414  mesh_.points(),
415  mesh_.faceAreas(),
416  mag(mesh_.faceAreas()),
417  avgFaceCentres,
418  avgCellCentres
419  );
420 
421 
422  // Calculate aspectratio weights
423  // - 0 if aratio < minAspect_
424  // - 1 if aratio >= maxAspect_
425  scalarField cellWeight, faceWeight;
426  calcAspectRatioWeights(cellWeight, faceWeight);
427 
428 
429  // Weight with average ones
430  vectorField faceCentres
431  (
432  (1.0-faceWeight)*mesh_.faceCentres()
433  + faceWeight*avgFaceCentres
434  );
435  vectorField cellCentres
436  (
437  (1.0-cellWeight)*mesh_.cellCentres()
438  + cellWeight*avgCellCentres
439  );
440 
441 
442  if (debug)
443  {
444  Pout<< "highAspectRatioFvGeometryScheme::movePoints() :"
445  << " highAspectRatio weight"
446  << " max:" << gMax(cellWeight) << " min:" << gMin(cellWeight)
447  << " average:" << gAverage(cellWeight) << endl;
448  }
449 
450  vectorField faceAreas(mesh_.faceAreas());
451  scalarField cellVolumes(mesh_.cellVolumes());
452 
453  // Store on primitiveMesh
454  //const_cast<fvMesh&>(mesh_).clearGeom();
456  (
457  std::move(faceCentres),
458  std::move(faceAreas),
459  std::move(cellCentres),
460  std::move(cellVolumes)
461  );
462  }
463 }
464 
465 
466 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1069
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
cellAspectRatio.H
Foam::gAverage
Type gAverage(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:604
wedgePolyPatch.H
highAspectRatioFvGeometryScheme.H
Foam::FatalIOError
IOerror FatalIOError
Foam::basicFvGeometryScheme
Default geometry calculation scheme. Slight stabilisation for bad meshes.
Definition: basicFvGeometryScheme.H:50
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::highAspectRatioFvGeometryScheme::movePoints
virtual void movePoints()
Do what is necessary if the mesh has moved.
Definition: highAspectRatioFvGeometryScheme.C:390
Foam::primitiveMesh::hasCellVolumes
bool hasCellVolumes() const noexcept
Definition: primitiveMeshI.H:201
syncTools.H
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::Field< scalar >
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::highAspectRatioFvGeometryScheme::calcAspectRatioWeights
void calcAspectRatioWeights(scalarField &cellWeight, scalarField &faceWeight) const
Calculate cell and face weight. Is 0 for cell < minAspect, 1 for.
Definition: highAspectRatioFvGeometryScheme.C:163
delta
scalar delta
Definition: LISASMDCalcMethod2.H:8
Foam::primitiveMesh::hasCellCentres
bool hasCellCentres() const noexcept
Definition: primitiveMeshI.H:189
Foam::primitiveMesh::hasFaceAreas
bool hasFaceAreas() const noexcept
Definition: primitiveMeshI.H:207
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::primitiveMesh::cellVolumes
const scalarField & cellVolumes() const
Definition: primitiveMeshCellCentresAndVols.C:96
Foam::cellAspectRatio
(Rough approximation of) cell aspect ratio
Definition: cellAspectRatio.H:51
emptyPolyPatch.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::highAspectRatioFvGeometryScheme::makeAverageCentres
static void makeAverageCentres(const polyMesh &mesh, const pointField &points, const pointField &faceAreas, const scalarField &magFaceAreas, pointField &faceCentres, pointField &cellCentres)
Helper : calculate (weighted) average face and cell centres.
Definition: highAspectRatioFvGeometryScheme.C:235
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:84
Foam::constant::mathematical::pi
constexpr scalar pi(M_PI)
f
labelList f(nPoints)
Foam::Vector
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:62
Foam::List< face >
Foam::primitiveMesh::resetGeometry
void resetGeometry(pointField &&faceCentres, pointField &&faceAreas, pointField &&cellCentres, scalarField &&cellVolumes)
Reset the local geometry.
Definition: primitiveMesh.C:284
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::primitiveMesh::faceCentres
const vectorField & faceCentres() const
Definition: primitiveMeshFaceCentresAndAreas.C:77
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::primitiveMesh::hasFaceCentres
bool hasFaceCentres() const noexcept
Definition: primitiveMeshI.H:195
Foam::gMin
Type gMin(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:593
Foam::primitiveMesh::updateGeom
virtual void updateGeom()
Update all geometric data.
Definition: primitiveMesh.C:365
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::fvGeometryScheme::mesh_
const fvMesh & mesh_
Hold reference to mesh.
Definition: fvGeometryScheme.H:72
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::primitiveMesh::faceAreas
const vectorField & faceAreas() const
Definition: primitiveMeshFaceCentresAndAreas.C:89