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-------------------------------------------------------------------------------
10License
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
38namespace Foam
39{
42 (
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
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;
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 const faceList& fs = mesh.faces();
251
252 // Start off from primitiveMesh faceCentres (preserved for triangles)
253 faceCentres.setSize(mesh.nFaces());
254
255 forAll(fs, facei)
256 {
257 const labelList& f = fs[facei];
258 const label nPoints = f.size();
259
260 if (nPoints == 3)
261 {
262 faceCentres[facei] = (1.0/3.0)*(p[f[0]] + p[f[1]] + p[f[2]]);
263 }
264 else
265 {
266 solveScalar sumA = 0.0;
267 solveVector sumAc = Zero;
268
269 for (label pi = 0; pi < nPoints; pi++)
270 {
271 const label nextPi(pi == nPoints-1 ? 0 : pi+1);
272 const solveVector nextPoint(p[f[nextPi]]);
273 const solveVector thisPoint(p[f[pi]]);
274
275 const solveVector eMid = 0.5*(thisPoint+nextPoint);
276 const solveScalar a = mag(nextPoint-thisPoint);
277
278 sumAc += a*eMid;
279 sumA += a;
280 }
281 // This is to deal with zero-area faces. Mark very small faces
282 // to be detected in e.g. processorPolyPatch.
283 if (sumA >= ROOTVSMALL)
284 {
285 faceCentres[facei] = sumAc/sumA;
286 }
287 else
288 {
289 // Unweighted average of points
290 sumAc = Zero;
291 for (label pi = 0; pi < nPoints; pi++)
292 {
293 sumAc += static_cast<solveVector>(p[f[pi]]);
294 }
295 faceCentres[facei] = sumAc/nPoints;
296 }
297 }
298 }
299
300
301 cellCentres.setSize(mesh.nCells());
302 cellCentres = Zero;
303 {
304 const labelList& own = mesh.faceOwner();
305 const labelList& nei = mesh.faceNeighbour();
306
307 Field<solveScalar> cellWeights(mesh.nCells(), Zero);
308 for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
309 {
310 const solveScalar magfA(magFaceAreas[facei]);
311 const vector weightedFc(magfA*faceCentres[facei]);
312
313 // Accumulate area-weighted face-centre
314 cellCentres[own[facei]] += weightedFc;
315 cellCentres[nei[facei]] += weightedFc;
316
317 // Accumulate weights
318 cellWeights[own[facei]] += magfA;
319 cellWeights[nei[facei]] += magfA;
320 }
321
322 const polyBoundaryMesh& pbm = mesh.boundaryMesh();
323 for (const polyPatch& pp : pbm)
324 {
325 if (!isA<emptyPolyPatch>(pp) && !isA<wedgePolyPatch>(pp))
326 {
327 for
328 (
329 label facei = pp.start();
330 facei < pp.start()+pp.size();
331 facei++
332 )
333 {
334 const solveScalar magfA(magFaceAreas[facei]);
335 const vector weightedFc(magfA*faceCentres[facei]);
336
337 cellCentres[own[facei]] += weightedFc;
338 cellWeights[own[facei]] += magfA;
339 }
340 }
341 }
342
343 forAll(cellCentres, celli)
344 {
345 if (mag(cellWeights[celli]) > VSMALL)
346 {
347 cellCentres[celli] /= cellWeights[celli];
348 }
349 }
350 }
351}
352
353
354// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
355
357(
358 const fvMesh& mesh,
359 const dictionary& dict
360)
361:
363 minAspect_(dict.get<scalar>("minAspect")),
364 maxAspect_(dict.get<scalar>("maxAspect"))
365{
367 {
369 << "minAspect " << minAspect_
370 << " has to be less than maxAspect " << maxAspect_
371 << exit(FatalIOError);
372 }
373 if (minAspect_ < 0 || maxAspect_ < 0)
374 {
376 << "Illegal aspect ratio : minAspect:" << minAspect_
377 << " maxAspect:" << maxAspect_
378 << exit(FatalIOError);
379 }
380
381 // Force local calculation
382 movePoints();
383}
384
385
386// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
387
389{
390 //basicFvGeometryScheme::movePoints();
392
393 if (debug)
394 {
395 Pout<< "highAspectRatioFvGeometryScheme::movePoints() : "
396 << "recalculating primitiveMesh centres" << endl;
397 }
398
399 if
400 (
401 !mesh_.hasCellCentres()
402 && !mesh_.hasFaceCentres()
403 && !mesh_.hasCellVolumes()
404 && !mesh_.hasFaceAreas()
405 )
406 {
407 // Use lower level to calculate the geometry
408 const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
409
410 pointField avgFaceCentres;
411 pointField avgCellCentres;
412 makeAverageCentres
413 (
414 mesh_,
415 mesh_.points(),
416 mesh_.faceAreas(),
417 mag(mesh_.faceAreas()),
418 avgFaceCentres,
419 avgCellCentres
420 );
421
422
423 // Calculate aspectratio weights
424 // - 0 if aratio < minAspect_
425 // - 1 if aratio >= maxAspect_
426 scalarField cellWeight, faceWeight;
427 calcAspectRatioWeights(cellWeight, faceWeight);
428
429
430 // Weight with average ones
431 vectorField faceCentres
432 (
433 (1.0-faceWeight)*mesh_.faceCentres()
434 + faceWeight*avgFaceCentres
435 );
436 vectorField cellCentres
437 (
438 (1.0-cellWeight)*mesh_.cellCentres()
439 + cellWeight*avgCellCentres
440 );
441
442
443 if (debug)
444 {
445 Pout<< "highAspectRatioFvGeometryScheme::movePoints() :"
446 << " highAspectRatio weight"
447 << " max:" << gMax(cellWeight) << " min:" << gMin(cellWeight)
448 << " average:" << gAverage(cellWeight) << endl;
449 }
450
451 vectorField faceAreas(mesh_.faceAreas());
452 scalarField cellVolumes(mesh_.cellVolumes());
453
454 // Store on primitiveMesh
455 //const_cast<fvMesh&>(mesh_).clearGeom();
456 const_cast<fvMesh&>(mesh_).primitiveMesh::resetGeometry
457 (
458 std::move(faceCentres),
459 std::move(faceAreas),
460 std::move(cellCentres),
461 std::move(cellVolumes)
462 );
463 }
464}
465
466
467// ************************************************************************* //
scalar delta
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:65
Default geometry calculation scheme. Slight stabilisation for bad meshes.
(Rough approximation of) cell aspect ratio
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
Abstract base class for geometry calculation schemes.
const fvMesh & mesh_
Hold reference to mesh.
virtual void movePoints()
Update basic geometric properties from provided points.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:91
Geometry calculation scheme with automatic stabilisation for high-aspect ratio cells.
virtual void movePoints()
Do what is necessary if the mesh has moved.
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.
void calcAspectRatioWeights(scalarField &cellWeight, scalarField &faceWeight) const
Calculate cell and face weight. Is 0 for cell < minAspect, 1 for.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1108
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1121
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1127
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
label nInternalFaces() const noexcept
Number of internal faces.
label nCells() const noexcept
Number of mesh cells.
label nFaces() const noexcept
Number of mesh faces.
virtual void updateGeom()
Update all geometric data.
void resetGeometry(pointField &&faceCentres, pointField &&faceAreas, pointField &&cellCentres, scalarField &&cellVolumes)
Reset the local geometry.
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
volScalarField & p
dynamicFvMesh & mesh
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
label nPoints
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
IOerror FatalIOError
Type gAverage(const FieldField< Field, Type > &f)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Type gMin(const FieldField< Field, Type > &f)
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Type gMax(const FieldField< Field, Type > &f)
labelList f(nPoints)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333