geometricElementTransformPointSmoother.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) 2024 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 
29 #include "cellPointConnectivity.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 namespace pointSmoothers
37 {
38  defineTypeNameAndDebug(geometricElementTransformPointSmoother, 0);
40  (
41  pointSmoother,
42  geometricElementTransformPointSmoother,
43  dictionary
44  );
45 }
46 }
47 
48 
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 
51 Foam::scalar
52 Foam::pointSmoothers::geometricElementTransformPointSmoother::cellQuality
53 (
54  const polyMesh& mesh,
55  const pointField& currentPoints,
56  const cellPointConnectivity& connectivity,
57  const label celli
58 )
59 {
60  const cell& cFaces = mesh.cells()[celli];
61  const labelList cPoints(cFaces.labels(mesh.faces()));
62 
63  // Calculate a transformed point for each cell point
64 
65  scalar cellQ = 0.0;
66  label nTets = 0;
67 
68  forAll(cPoints, cPointi)
69  {
70  const label pointi(cPoints[cPointi]);
71  const point& pt = currentPoints[pointi];
72  const labelList& pPoints
73  (
74  connectivity.cellPointPoints()[celli][cPointi]
75  );
76  if (pPoints.size() != 3)
77  {
78  WarningInFunction<< "Cell:" << celli
79  << " point:" << pointi
80  << " connected points:" << pPoints << endl;
81  }
82  else
83  {
84  const Tensor<scalar> mA
85  (
86  currentPoints[pPoints[0]] - pt,
87  currentPoints[pPoints[1]] - pt,
88  currentPoints[pPoints[2]] - pt
89  );
90  const scalar sigma(det(mA));
91 
92  if (sigma < ROOTVSMALL)
93  {
94  return 0;
95  }
96 
97  // 3 * pow(sigma, 2.0/3.0)/magSqr(mA)
98  const scalar tetQ =
99  scalar(3) * Foam::cbrt(Foam::sqr(sigma)) / magSqr(mA);
100  cellQ += tetQ;
101  nTets++;
102  }
103  }
104 
105  return cellQ/nTets;
106 }
107 
108 
109 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
110 
113 (
114  const polyMesh& mesh,
115  const dictionary& dict
116 )
117 :
119  transformationParameter_
120  (
121  readScalar(dict.lookup("transformationParameter"))
122  )
123 {}
124 
125 
126 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
127 
129 (
130  const labelList& facesToMove,
131  const pointField& oldPoints,
132  const pointField& currentPoints,
133  const pointField& faceCentres,
134  const vectorField& faceAreas,
135  const pointField& cellCentres,
136  const scalarField& cellVolumes,
137  vectorField& pointDisplacement
138 ) const
139 {
140  // Lookup or generate the cell-point connectivity/
141  const cellPointConnectivity& connectivity =
143  (
144  mesh()
145  );
146 
147  // Number of points used in each average
148  labelField counts(mesh().nPoints(), -1);
149 
150  // Reset the displacements which are about to be calculated
151  reset(facesToMove, counts, pointDisplacement);
152 
153  // Identify the cells which are to be moved
154  labelHashSet cellsToMove(facesToMove.size()*2/3);
155  forAll(facesToMove, faceToMoveI)
156  {
157  const label faceI(facesToMove[faceToMoveI]);
158 
159  cellsToMove.insert(mesh().faceOwner()[faceI]);
160 
161  if (mesh().isInternalFace(faceI))
162  {
163  cellsToMove.insert(mesh().faceNeighbour()[faceI]);
164  }
165  }
166 
167  // Transformed point field
168  pointField transformedPoints(currentPoints);
169 
170  // Calculate the internal transformations
171  forAllConstIter(labelHashSet, cellsToMove, iter)
172  {
173  const label cellI(iter.key());
174 
175  const cell& cFaces
176  (
177  mesh().cells()[cellI]
178  );
179  const labelList cPoints
180  (
181  cFaces.labels(mesh().faces())
182  );
183  const edgeList cEdges
184  (
185  cFaces.edges(mesh().faces())
186  );
187 
188  // Calculate a transformed point for each cell point
189  forAll(cPoints, cPointI)
190  {
191  const label pointI(cPoints[cPointI]);
192 
193  if (counts[pointI] == -1) continue;
194 
195  const labelList& pPoints
196  (
197  connectivity.cellPointPoints()[cellI][cPointI]
198  );
199  const labelList& pFaces
200  (
201  connectivity.cellPointFaces()[cellI][cPointI]
202  );
203  const label nPPoints(pPoints.size());
204 
205  // Initial guess of the dual face centre
206  vector dualAverage(vector::zero);
207  forAll(pPoints, pPointI)
208  {
209  dualAverage +=
210  currentPoints[pPoints[pPointI]]
211  + faceCentres[pFaces[pPointI]];
212  }
213  dualAverage /= 2*nPPoints;
214 
215  // Calculate the dual face centre and normal
216  vector dualNormal(vector::zero);
217  forAll(pPoints, pPointI)
218  {
219  const label nextPPointI((pPointI + 1) % nPPoints);
220 
221  point edgeCentre
222  (
223  0.5
224  *(
225  currentPoints[pPoints[pPointI]]
226  + currentPoints[pointI]
227  )
228  );
229  point nextFaceCentre
230  (
231  faceCentres[pFaces[nextPPointI]]
232  );
233  point nextEdgeCentre
234  (
235  0.5
236  *(
237  currentPoints[pPoints[nextPPointI]]
238  + currentPoints[pointI]
239  )
240  );
241 
242  dualNormal +=
243  (nextFaceCentre - edgeCentre)
244  ^(edgeCentre - dualAverage);
245  dualNormal +=
246  (nextEdgeCentre - nextFaceCentre)
247  ^(nextFaceCentre - dualAverage);
248  }
249  vector dualNormalHat(dualNormal/max(mag(dualNormal), ROOTVSMALL));
250 
251  scalar sumA(0);
252  vector sumAc(vector::zero);
253  forAll(pPoints, pPointI)
254  {
255  const label nextPPointI((pPointI + 1) % nPPoints);
256 
257  point edgeCentre
258  (
259  0.5
260  *(
261  currentPoints[pPoints[pPointI]]
262  + currentPoints[pointI]
263  )
264  );
265  point nextFaceCentre
266  (
267  faceCentres[pFaces[nextPPointI]]
268  );
269  point nextEdgeCentre
270  (
271  0.5
272  *(
273  currentPoints[pPoints[nextPPointI]]
274  + currentPoints[pointI]
275  )
276  );
277 
278  vector c1 = edgeCentre + nextFaceCentre + dualAverage;
279  vector c2 = nextFaceCentre + nextEdgeCentre + dualAverage;
280 
281  vector n1 =
282  (nextFaceCentre - edgeCentre)
283  ^(edgeCentre - dualAverage);
284  vector n2 =
285  (nextEdgeCentre - nextFaceCentre)
286  ^(nextFaceCentre - dualAverage);
287 
288  scalar a1 = n1 & dualNormalHat;
289  scalar a2 = n2 & dualNormalHat;
290 
291  sumA += a1 + a2;
292  sumAc += a1*c1 + a2*c2;
293  }
294 
295  const vector dualCentre(sumAc/max(sumA, ROOTVSMALL)/3);
296 
297  // Calculate the transformed point
298  transformedPoints[pointI] =
299  dualCentre
300  + transformationParameter_
301  *dualNormal/sqrt(max(mag(dualNormal), ROOTVSMALL));
302  }
303 
304  // Length scale
305  scalar lengthScale(0), transformedLengthScale(0);
306  forAll(cEdges, cEdgeI)
307  {
308  lengthScale +=
309  cEdges[cEdgeI].mag(currentPoints);
310  transformedLengthScale +=
311  cEdges[cEdgeI].mag(transformedPoints);
312  }
313  lengthScale /= cEdges.size();
314  transformedLengthScale /= cEdges.size();
315 
316  const scalar lengthScaleRatio =
317  (
318  (transformedLengthScale > SMALL)
319  ? lengthScale/transformedLengthScale
320  : scalar(0)
321  );
322 
323  // Add the displacement to the average
324  forAll(cPoints, cPointI)
325  {
326  const label pointI(cPoints[cPointI]);
327 
328  if (counts[pointI] == -1) continue;
329 
330  const vector newPoint
331  (
332  cellCentres[cellI]
333  + lengthScaleRatio
334  *(
335  transformedPoints[pointI]
336  - cellCentres[cellI]
337  )
338  );
339 
340  ++ counts[pointI];
341 
342  pointDisplacement[pointI] += newPoint - oldPoints[pointI];
343  }
344  }
345 
346  // Reset all the boundary faces
347  reset(facesToMove, counts, pointDisplacement, false);
348 
349  // Calculate the boundary transformations
350  forAll(facesToMove, faceToMoveI)
351  {
352  const label faceI(facesToMove[faceToMoveI]);
353 
354  if (!isInternalOrProcessorFace(faceI))
355  {
356  const labelList& fPoints(mesh().faces()[faceI]);
357 
358  // Face normal
359  vector faceNormalHat(faceAreas[faceI]);
360  faceNormalHat /= max(SMALL, mag(faceNormalHat));
361 
362  // Calculate a transformed point for each face point
363  forAll(fPoints, fPointI)
364  {
365  const label pointI(fPoints[fPointI]);
366 
367  const label fPointIPrev
368  (
369  (fPointI - 1 + fPoints.size()) % fPoints.size()
370  );
371  const label fPointINext
372  (
373  (fPointI + 1) % fPoints.size()
374  );
375 
376  const vector dualCentre
377  (
378  currentPoints[pointI]/2
379  + (
380  currentPoints[fPoints[fPointINext]]
381  + currentPoints[fPoints[fPointIPrev]]
382  )/4
383  );
384  const vector dualNormal
385  (
386  (
387  currentPoints[fPoints[fPointINext]]
388  - currentPoints[fPoints[fPointIPrev]]
389  )/2
390  ^faceNormalHat
391  );
392 
393  transformedPoints[pointI] =
394  dualCentre
395  + transformationParameter_
396  *dualNormal/sqrt(max(mag(dualNormal), ROOTVSMALL));
397  }
398 
399  // Length scale
400  scalar lengthScale(0), transformedLengthScale(0);
401  forAll(fPoints, fPointI)
402  {
403  const label fPointINext((fPointI + 1)%fPoints.size());
404 
405  const label pointI(fPoints[fPointI]);
406  const label pointINext(fPoints[fPointINext]);
407 
408  lengthScale += mag
409  (
410  currentPoints[pointINext] - currentPoints[pointI]
411  );
412  transformedLengthScale += mag
413  (
414  transformedPoints[pointINext] - transformedPoints[pointI]
415  );
416  }
417  lengthScale /= fPoints.size();
418  transformedLengthScale /= fPoints.size();
419 
420  const scalar lengthScaleRatio
421  (
422  (transformedLengthScale > SMALL)
423  ? lengthScale/transformedLengthScale
424  : scalar(0)
425  );
426 
427  // Add the displacement to the average
428  forAll(fPoints, fPointI)
429  {
430  const label pointI(fPoints[fPointI]);
431 
432  const vector newPoint
433  (
434  faceCentres[faceI]
435  + lengthScaleRatio
436  *(
437  transformedPoints[pointI]
438  - faceCentres[faceI]
439  )
440  );
441 
442  ++ counts[pointI];
443 
444  pointDisplacement[pointI] += newPoint - oldPoints[pointI];
445  }
446  }
447  }
448 
449  // Average
450  average(facesToMove, counts, pointDisplacement);
451 }
452 
453 
455 Foam::pointSmoothers::geometricElementTransformPointSmoother::cellQuality
456 (
457  const polyMesh& mesh,
458  const pointField& currentPoints
459 )
460 {
461  const cellPointConnectivity& connectivity =
463  (
464  mesh
465  );
466 
468  scalarField& fld = tfld.ref();
469 
470  forAll(fld, celli)
471  {
472  fld[celli] = cellQuality(mesh, currentPoints, connectivity, celli);
473  }
474 
475  return tfld;
476 }
477 
478 
479 // ************************************************************************* //
const polyMesh & mesh() const
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
dimensioned< Type > average(const DimensionedField< Type, GeoMesh > &f1)
Class calculates cell quality measures.
Definition: cellQuality.H:47
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
Abstract base class for point smoothing methods. Handles parallel communication via reset and average...
Definition: pointSmoother.H:50
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
static const Type & New(const Mesh &mesh, Args &&... args)
Get existing or create MeshObject registered with typeName.
Definition: MeshObject.C:53
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
dimensionedSymmTensor sqr(const dimensionedVector &dv)
const dimensionedScalar c2
Second radiation constant: default SI units: [m.K].
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
const cellList & cells() const
dimensionedScalar det(const dimensionedSphericalTensor &dt)
Lookup type of boundary radiation properties.
Definition: lookup.H:57
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:478
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
Macros for easy insertion into run-time selection tables.
geometricElementTransformPointSmoother(const polyMesh &mesh, const dictionary &dict)
Construct from a dictionary and a mesh.
#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
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
const cellShapeList & cells
virtual void calculate(const labelList &facesToMove, const pointField &oldPoints, const pointField &currentPoints, const pointField &faceCentres, const vectorField &faceAreas, const pointField &cellCentres, const scalarField &cellVolumes, vectorField &pointDisplacement) const
Calculate the point displacements.
addToRunTimeSelectionTable(pointSmoother, equipotentialPointSmoother, dictionary)
label nPoints
const labelListListList & cellPointFaces() const
Access the point-face connections.
dimensionedScalar cbrt(const dimensionedScalar &ds)
This class provides ordered connectivity for each point of each cell. Lists are available of the poin...
Vector< scalar > vector
Definition: vector.H:57
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells].reset(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
vector point
Point is a vector.
Definition: point.H:37
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
List< label > labelList
A List of labels.
Definition: List.H:62
A class for managing temporary objects.
Definition: HashPtrTable.H:50
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
defineTypeNameAndDebug(equipotentialPointSmoother, 0)
Namespace for OpenFOAM.
const labelListListList & cellPointPoints() const
Access the point-point connections.