wallDistAddressing.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) 2023-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 
28 #include "FaceCellWave.H"
29 #include "wallDistAddressing.H"
30 #include "wallPointAddressing.H"
32 #include "surfaceFields.H"
33 #include "wallPolyPatch.H"
34 #include "patchDistMethod.H"
35 #include "OBJstream.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
42 }
43 
44 
45 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
46 
48 (
53 ) const
54 {
55  // Extract volField. See patchWave::getValues
56 
57  label nIllegal = 0;
58  forAll(allCellInfo, celli)
59  {
60  const scalar dist = allCellInfo[celli].distSqr();
61 
62  if (allCellInfo[celli].valid(wave.data()))
63  {
64  y[celli] = Foam::sqrt(dist);
65  }
66  else
67  {
68  y[celli] = dist;
69  ++nIllegal;
70  }
71  }
72 
73  // Copy boundary values
74  auto& bfld = y.boundaryFieldRef();
75 
76  for (auto& pfld : bfld)
77  {
78  scalarField patchField(pfld.size(), Zero);
79 
80  forAll(pfld, patchFacei)
81  {
82  const label meshFacei = pfld.patch().start() + patchFacei;
83  const scalar dist = allFaceInfo[meshFacei].distSqr();
84 
85  if (allFaceInfo[meshFacei].valid(wave.data()))
86  {
87  // Adding SMALL to avoid problems with /0 in the turbulence
88  // models
89  patchField[patchFacei] = Foam::sqrt(dist) + SMALL;
90  }
91  else
92  {
93  patchField[patchFacei] = dist;
94  ++nIllegal;
95  }
96  }
97  pfld = patchField;
98  }
99 
100  return nIllegal;
101 }
102 
103 
105 (
106  const label item,
107  const labelPair& data,
108  label& untransformi,
109  label& transformi,
110  labelPairList& transformedWallInfo
111 )
112 {
113  const auto& gt = mesh_.globalData().globalTransforms();
114 
115  if (gt.transformIndex(data) == gt.nullTransformIndex())
116  {
117  // Store item and global index of untransformed data
118  const label proci = gt.processor(data);
119  const label index = gt.index(data);
120  untransformedItems_[untransformi] = item;
121  untransformedSlots_[untransformi++] =
122  globalWallsPtr_().toGlobal(proci, index);
123  }
124  else
125  {
126  // Store item and transformed data
127  transformedItems_[transformi] = item;
128  transformedWallInfo[transformi++] = data;
129  }
130 }
131 
132 
134 {
135  y = dimensionedScalar("yWall", dimLength, GREAT);
136 
137  const auto& C = mesh_.C();
138  const auto& gt = mesh_.globalData().globalTransforms();
139 
140  label nWalls = 0;
141  for (const label patchi : patchIDs_)
142  {
143  nWalls += C.boundaryField()[patchi].size();
144  }
145 
146  globalWallsPtr_.reset(new globalIndex(nWalls));
147  const globalIndex& globalWalls = globalWallsPtr_();
148 
149  DynamicList<label> seedFaces(nWalls);
150  DynamicList<wallPointAddressing> seedInfo(nWalls);
151 
152 
153  nWalls = 0;
154  for (const label patchi : patchIDs_)
155  {
156  const auto& fc = C.boundaryField()[patchi];
157  const auto areaFraction(fc.patch().patch().areaFraction());
158 
159  forAll(fc, patchFacei)
160  {
161  if
162  (
163  !areaFraction
164  || (areaFraction()[patchFacei] > 0.5) // mostly wall
165  )
166  {
167  seedFaces.append(fc.patch().start()+patchFacei);
168  seedInfo.append
169  (
170  wallPointAddressing
171  (
172  fc[patchFacei],
173  gt.encode
174  (
176  nWalls,
177  gt.nullTransformIndex()
178  ),
179  scalar(0.0)
180  )
181  );
182  }
183  nWalls++;
184  }
185  }
186 
187  List<wallPointAddressing> allCellInfo(mesh_.nCells());
188  // Initialise the passive data (since no mesh reference in the constructor
189  // of wallPointAddressing)
190  forAll(allCellInfo, celli)
191  {
192  allCellInfo[celli].data() = gt.encode
193  (
195  celli,
196  gt.nullTransformIndex()
197  );
198  }
199  List<wallPointAddressing> allFaceInfo(mesh_.nFaces());
200  forAll(allFaceInfo, facei)
201  {
202  allFaceInfo[facei].data() = gt.encode
203  (
205  facei,
206  gt.nullTransformIndex()
207  );
208  }
209 
210  // Propagate information inwards
211  FaceCellWave<wallPointAddressing> wave
212  (
213  mesh_,
214  seedFaces,
215  seedInfo,
216  allFaceInfo,
217  allCellInfo,
218  mesh_.globalData().nTotalCells()+1
219  );
220 
221 
222  // Extract wall distance
223  // ~~~~~~~~~~~~~~~~~~~~~
224 
225  getValues(wave, allCellInfo, allFaceInfo, y);
226 
227 
228  const labelHashSet patchSet(patchIDs_);
229 
230  // Correct wall cells for true distance
231  // - store for corrected cells the nearest wall face
232  // - update distance field (y) for these cells
233  Map<label> cellToWallFace;
234  if (correctWalls_)
235  {
236  cellToWallFace.reserve(nWalls);
237  correctBoundaryFaceCells
238  (
239  patchSet,
240  y,
241  cellToWallFace
242  );
243 
244  correctBoundaryPointCells
245  (
246  patchSet,
247  y,
248  cellToWallFace
249  );
250  }
251 
252  // Make sure boundary values are up to date
253  y.correctBoundaryConditions();
254 
255 
256  // Extract all addressing
257  // ~~~~~~~~~~~~~~~~~~~~~~
258  // - untransformed : -local cell/boundary, -nearest (global) wall
259  // - transformed : -local cell/boundary, -nearest (global) wall
260 
261  label untransformi = 0;
262  untransformedItems_.resize(mesh_.nCells()+mesh_.nBoundaryFaces());
263  untransformedSlots_.resize(untransformedItems_.size());
264 
265  label transformi = 0;
266  transformedItems_.resize(mesh_.nCells()+mesh_.nBoundaryFaces());
267  labelPairList transformedWallInfo(transformedItems_.size());
268 
269  for (label celli = 0; celli < mesh_.nCells(); celli++)
270  {
271  const auto cellFnd = cellToWallFace.find(celli);
272  if (cellFnd)
273  {
274  const label wallFacei = cellFnd();
275  const auto& data = allFaceInfo[wallFacei].data();
276  addItem(celli, data, untransformi, transformi, transformedWallInfo);
277  }
278  else if (allCellInfo[celli].valid(wave.data()))
279  {
280  const auto& data = allCellInfo[celli].data();
281  addItem(celli, data, untransformi, transformi, transformedWallInfo);
282  }
283  }
284  untransformedPatchStarts_.resize(mesh_.boundary().size()+1);
285  transformedPatchStarts_.resize(mesh_.boundary().size()+1);
286  for (const auto& pp : mesh_.boundary())
287  {
288  untransformedPatchStarts_[pp.index()] = untransformi;
289  transformedPatchStarts_[pp.index()] = transformi;
290 
291  forAll(pp, patchFacei)
292  {
293  const label facei = pp.start()+patchFacei;
294  if (allFaceInfo[facei].valid(wave.data()))
295  {
296  const auto& data = allFaceInfo[facei].data();
297  addItem
298  (
299  facei,
300  data,
301  untransformi,
302  transformi,
303  transformedWallInfo
304  );
305  }
306  }
307  }
308 
309  untransformedItems_.resize(untransformi);
310  untransformedSlots_.resize(untransformi);
311  untransformedPatchStarts_.back() = untransformi;
312  transformedItems_.resize(transformi);
313  transformedWallInfo.resize(transformi);
314  transformedPatchStarts_.back() = transformi;
315 
316  if (debug)
317  {
318  Pout<< typeName
319  << " : untransformed:" << untransformi
320  << " transformed:" << transformi
321  << " out of nWalls:" << nWalls
322  << " untransformStart:" << flatOutput(untransformedPatchStarts_)
323  << " transformStart:" << flatOutput(transformedPatchStarts_)
324  << endl;
325  }
326 
327  List<Map<label>> compactMap;
328  mapPtr_.reset
329  (
330  new mapDistribute
331  (
332  globalWalls, // globalIndex
333  untransformedSlots_, // untransformedElements
334 
335  gt, // globalIndexAndTransform
336  transformedWallInfo, // transformedElements
337  transformedSlots_, // transformedIndices
338  compactMap
339  )
340  );
341 
342  if (debug & 2)
343  {
344  // Use the obtained map to write nearest
345  {
346  OBJstream os(mesh_.polyMesh::path()/"nearest.obj");
347  Pout<< typeName
348  << " : writing line from cell/face to nearest wall face to "
349  << os.name() << endl;
350 
351  // Seed all wall faces with centroid and override all other
352  // cells/faces with that of nearest wall
353  volVectorField wallCentre(mesh_.C());
354  this->map(wallCentre, mapDistribute::transformPosition());
355 
356  // Seed all wall faces with normal and override all other
357  // cells/faces with that of nearest wall
359  (
360  IOobject
361  (
362  "n" & patchTypeName_,
363  mesh_.time().timeName(),
364  mesh_,
366  ),
367  mesh_,
369  patchDistMethod::patchTypes<vector>(mesh_, patchSet)
370  );
371  // Calculate normal
372  for (const label patchi : patchIDs_)
373  {
374  auto& pnf = wallNormal.boundaryFieldRef()[patchi];
375  pnf == pnf.patch().nf();
376  }
377  this->map(wallNormal, mapDistribute::transform());
378 
379  forAll(wallCentre, celli)
380  {
381  const point& cc = mesh_.C()[celli];
382  const point& wallC = wallCentre[celli];
383  const vector& wallN = wallNormal[celli];
384  os.write(linePointRef(cc, wallC), wallN, wallN);
385  }
386  }
387  }
388 }
389 
390 
391 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
392 
394 (
395  const fvMesh& mesh,
396  const bool correctWalls,
397  const label updateInterval
398 )
399 :
400  // Register as "wallDistAddressing"
401  MeshObject_type(mesh),
402  cellDistFuncs(mesh),
403  patchIDs_(mesh.boundaryMesh().findPatchIDs<wallPolyPatch>().sortedToc()),
404  patchTypeName_("wall"),
405  updateInterval_(updateInterval),
406  correctWalls_(correctWalls),
407  requireUpdate_(true),
408  y_
409  (
410  IOobject
411  (
412  "y" & patchTypeName_,
413  mesh.time().timeName(),
414  mesh.thisDb(),
415  IOobjectOption::NO_REGISTER
416  ),
417  mesh,
418  dimensionedScalar("y", dimLength, GREAT) // Same as wallDistData
419  )
420 {
421  movePoints();
422 }
423 
424 
426 (
427  const word& patchTypeName,
428  const fvMesh& mesh,
429  const labelList& patchIDs,
430  const bool correctWalls,
431  const label updateInterval
432 )
433 :
434  MeshObject_type(patchTypeName, mesh),
436  patchIDs_(patchIDs),
437  patchTypeName_(patchTypeName),
438  updateInterval_(updateInterval),
439  correctWalls_(correctWalls),
440  requireUpdate_(true),
441  y_
442  (
443  IOobject
444  (
445  "y" & patchTypeName_,
446  mesh.time().timeName(),
447  mesh.thisDb(),
448  IOobjectOption::NO_REGISTER
449  ),
450  mesh,
451  dimensionedScalar("y", dimLength, GREAT) // Same as wallDistData
452  )
453 {
454  movePoints();
455 }
456 
457 
458 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
461 {} // mapDistribute was forward declared
462 
463 
464 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
465 
467 {
468  if
469  (
470  (updateInterval_ > 0)
471  && ((mesh_.time().timeIndex() % updateInterval_) == 0)
472  )
473  {
474  requireUpdate_ = true;
475  }
476 
477  if (requireUpdate_)
478  {
479  DebugInfo<< "Updating wall distance" << endl;
480 
481  requireUpdate_ = false;
482 
483  correct(y_);
484 
485  return true;
486  }
487 
488  return false;
489 }
490 
491 
492 void Foam::wallDistAddressing::updateMesh(const mapPolyMesh& mpm)
493 {
494  // Force update if performing topology change
495  // Note: needed?
496  // - field would have been mapped, so if using updateInterval option (!= 1)
497  // live with error associated of not updating and use mapped values?
498  requireUpdate_ = true;
499  movePoints();
500 }
501 
502 
503 // ************************************************************************* //
Foam::surfaceFields.
const labelList patchIDs(pbm.indices(polyPatchNames, true))
const volScalarField & y() const noexcept
Return reference to cached distance-to-wall field. Unvisited.
List< wallPoints > allCellInfo(mesh_.nCells())
virtual Ostream & write(const char c) override
Write character.
Definition: OBJstream.C:69
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:153
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition: OSstream.H:134
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
wallDistAddressing(const wallDistAddressing &)=delete
No copy construct.
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Definition: FaceCellWave.H:206
label getValues(const FaceCellWave< wallPointAddressing > &wave, const List< wallPointAddressing > &allCellInfo, const List< wallPointAddressing > &allFaceInfo, volScalarField &y) const
Extract FaceCellWave data.
void correct(volScalarField &y)
Extract nearest-patch distance data.
const TrackingData & data() const noexcept
Additional data to be passed into container.
Definition: FaceCellWave.H:506
List< labelPair > labelPairList
List of labelPair.
Definition: labelPair.H:33
const dimensionSet dimless
Dimensionless.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1086
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:76
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
Collection of functions used in wall distance calculation.
Definition: cellDistFuncs.H:59
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:72
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
word timeName
Definition: getTimeIndex.H:3
scalar y
dynamicFvMesh & mesh
line< point, const point & > linePointRef
A line using referred points.
Definition: line.H:66
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
virtual ~wallDistAddressing()
Destructor.
Vector< scalar > vector
Definition: vector.H:57
label find(const T &val) const
Find index of the first occurrence of the value.
Definition: UList.C:173
#define DebugInfo
Report an information message using Foam::Info.
virtual void updateMesh(const mapPolyMesh &)
Update the y-field when the mesh changes.
int debug
Static debugging option.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
Info<< "Predicted p max-min : "<< max(p).value()<< " "<< min(p).value()<< endl;rho==max(psi *p+alphal *rhol0+((alphav *psiv+alphal *psil) - psi) *pSat, rhoMin);# 1 "/home/chef2/andy/OpenFOAM/release/v2406/OpenFOAM-v2406/applications/solvers/multiphase/cavitatingFoam/alphavPsi.H" 1{ alphav=clamp((rho - rholSat)/(rhovSat - rholSat), zero_one{});alphal=1.0 - alphav;Info<< "max-min alphav: "<< max(alphav).value()<< " "<< min(alphav).value()<< endl;psiModel-> correct()
Definition: pEqn.H:63
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
volScalarField & C
vector point
Point is a vector.
Definition: point.H:37
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to &#39;true&#39; entries.
Definition: BitOps.C:195
vector wallNormal(Zero)
virtual bool movePoints()
Update the y-field when the mesh moves.
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
List< wallPoints > allFaceInfo(mesh_.nFaces())
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Do not request registration (bool: false)
void addItem(const label item, const labelPair &data, label &untransformi, label &transformi, labelPairList &transformedWallInfo)
Store nearest-data to cell or boundary face.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
Variant of wallDist that uses meshWave and stores the addressing.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127