turbulentDFSEMInletFvPatchVectorField.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) 2015 OpenFOAM Foundation
9  Copyright (C) 2016-2020 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 
30 #include "volFields.H"
32 #include "fvPatchFieldMapper.H"
33 #include "momentOfInertia.H"
34 #include "OFstream.H"
35 #include "globalIndex.H"
36 #include "rawIOField.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 Foam::label Foam::turbulentDFSEMInletFvPatchVectorField::seedIterMax_ = 1000;
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
44 void Foam::turbulentDFSEMInletFvPatchVectorField::writeEddyOBJ() const
45 {
46  {
47  // Output the bounding box
48  OFstream os(db().time().path()/"eddyBox.obj");
49 
50  const polyPatch& pp = this->patch().patch();
51  const labelList& boundaryPoints = pp.boundaryPoints();
52  const pointField& localPoints = pp.localPoints();
53 
54  vector offset = patchNormal_*maxSigmaX_;
55  forAll(boundaryPoints, i)
56  {
57  point p = localPoints[boundaryPoints[i]];
58  p += offset;
59  os << "v " << p.x() << " " << p.y() << " " << p.z() << nl;
60  }
61 
62  forAll(boundaryPoints, i)
63  {
64  point p = localPoints[boundaryPoints[i]];
65  p -= offset;
66  os << "v " << p.x() << " " << p.y() << " " << p.z() << nl;
67  }
68 
69  // Draw lines between points
70  // Note: need to order to avoid crossing patch
71  //const label nPoint = boundaryPoints.size();
72  //
73  //forAll(boundaryPoints, i)
74  //{
75  // label i1 = i;
76  // label i2 = (i + 1) % nPoint;
77  // os << "l " << i1 << " " << i2 << nl;
78  //}
79  //
80  //forAll(boundaryPoints, i)
81  //{
82  // label i1 = i + nPoint;
83  // label i2 = ((i + 1) % nPoint) + nPoint;
84  // os << "l " << i1 << " " << i2 << nl;
85  //}
86  }
87 
88  {
89  const Time& time = db().time();
90  OFstream os
91  (
92  time.path()/"eddies_" + Foam::name(time.timeIndex()) + ".obj"
93  );
94 
95  label pointOffset = 0;
96  forAll(eddies_, eddyI)
97  {
98  const eddy& e = eddies_[eddyI];
99  pointOffset += e.writeSurfaceOBJ(pointOffset, patchNormal_, os);
100  }
101  }
102 }
103 
104 
105 void Foam::turbulentDFSEMInletFvPatchVectorField::writeLumleyCoeffs() const
106 {
107  // Output list of xi vs eta
108 
109  // Before interpolation/raw data
110  if (interpolateR_)
111  {
112  const fileName valsFile
113  (
114  fileName
115  (
116  this->db().time().globalPath()
117  /this->db().time().constant()
118  /"boundaryData"
119  /this->patch().name()
120  /"0"
121  /"R"
122  )
123  );
124 
125  IOobject io
126  (
127  valsFile, // absolute path
128  this->db().time(),
131  false, // no need to register
132  true // is global object (currently not used)
133  );
134 
135  const rawIOField<symmTensor> Rexp(io, false);
136 
137  OFstream os(db().time().path()/"lumley_input.out");
138 
139  os << "# xi" << token::TAB << "eta" << endl;
140 
141  forAll(Rexp, faceI)
142  {
143  // Normalised anisotropy tensor
144  symmTensor devR = dev(Rexp[faceI]/(tr(Rexp[faceI])));
145 
146  // Second tensor invariant
147  scalar ii = min(0, invariantII(devR));
148 
149  // Third tensor invariant
150  scalar iii = invariantIII(devR);
151 
152  // xi, eta
153  // See Pope - characterization of Reynolds-stress anisotropy
154  scalar xi = cbrt(0.5*iii);
155  scalar eta = sqrt(-ii/3.0);
156  os << xi << token::TAB << eta << token::TAB
157  << ii << token::TAB << iii << endl;
158  }
159  }
160 
161  // After interpolation
162  {
163  OFstream os(db().time().path()/"lumley_interpolated.out");
164 
165  os << "# xi" << token::TAB << "eta" << endl;
166 
167  forAll(R_, faceI)
168  {
169  // Normalised anisotropy tensor
170  symmTensor devR = dev(R_[faceI]/(tr(R_[faceI])));
171 
172  // Second tensor invariant
173  scalar ii = min(0, invariantII(devR));
174 
175  // Third tensor invariant
176  scalar iii = invariantIII(devR);
177 
178  // xi, eta
179  // See Pope - characterization of Reynolds-stress anisotropy
180  scalar xi = cbrt(0.5*iii);
181  scalar eta = sqrt(-ii/3.0);
182  os << xi << token::TAB << eta << token::TAB
183  << ii << token::TAB << iii << endl;
184  }
185  }
186 }
187 
188 
190 Foam::turbulentDFSEMInletFvPatchVectorField::patchMapper() const
191 {
192  // Initialise interpolation (2D planar interpolation by triangulation)
193  if (!mapperPtr_)
194  {
195  const fileName samplePointsFile
196  (
197  this->db().time().globalPath()
198  /this->db().time().constant()
199  /"boundaryData"
200  /this->patch().name()
201  /"points"
202  );
203 
204  IOobject io
205  (
206  samplePointsFile, // absolute path
207  this->db().time(),
210  false, // no need to register
211  true // is global object (currently not used)
212  );
213 
214  // Read data
215  const rawIOField<point> samplePoints(io, false);
216 
217 
219  << " Read " << samplePoints.size() << " sample points from "
220  << samplePointsFile << endl;
221 
222 
223  // tbd: run-time selection
224  bool nearestOnly =
225  (
226  !mapMethod_.empty()
227  && mapMethod_ != "planarInterpolation"
228  );
229 
230  // Allocate the interpolator
231  mapperPtr_.reset
232  (
233  new pointToPointPlanarInterpolation
234  (
235  samplePoints,
236  this->patch().patch().faceCentres(),
237  perturb_,
238  nearestOnly
239  )
240  );
241  }
242 
243  return *mapperPtr_;
244 }
245 
246 
247 void Foam::turbulentDFSEMInletFvPatchVectorField::initialisePatch()
248 {
249  const vectorField nf(patch().nf());
250 
251  // Patch normal points into domain
252  patchNormal_ = -gAverage(nf);
253 
254  // Check that patch is planar
255  scalar error = max(magSqr(patchNormal_ + nf));
256 
257  if (error > SMALL)
258  {
260  << "Patch " << patch().name() << " is not planar"
261  << endl;
262  }
263 
264  patchNormal_ /= mag(patchNormal_) + ROOTVSMALL;
265 
266 
267  // Decompose the patch faces into triangles to enable point search
268 
269  const polyPatch& patch = this->patch().patch();
270  const pointField& points = patch.points();
271 
272  // Triangulate the patch faces and create addressing
273  DynamicList<label> triToFace(2*patch.size());
274  DynamicList<scalar> triMagSf(2*patch.size());
275  DynamicList<face> triFace(2*patch.size());
276  DynamicList<face> tris(5);
277 
278  // Set zero value at the start of the tri area list
279  triMagSf.append(0.0);
280 
281  forAll(patch, faceI)
282  {
283  const face& f = patch[faceI];
284 
285  tris.clear();
286  f.triangles(points, tris);
287 
288  forAll(tris, i)
289  {
290  triToFace.append(faceI);
291  triFace.append(tris[i]);
292  triMagSf.append(tris[i].mag(points));
293  }
294  }
295 
296  forAll(sumTriMagSf_, i)
297  {
298  sumTriMagSf_[i] = 0.0;
299  }
300 
301  sumTriMagSf_[Pstream::myProcNo() + 1] = sum(triMagSf);
302 
303  Pstream::listCombineGather(sumTriMagSf_, maxEqOp<scalar>());
304  Pstream::listCombineScatter(sumTriMagSf_);
305 
306  for (label i = 1; i < triMagSf.size(); i++)
307  {
308  triMagSf[i] += triMagSf[i-1];
309  }
310 
311  // Transfer to persistent storage
312  triFace_.transfer(triFace);
313  triToFace_.transfer(triToFace);
314  triCumulativeMagSf_.transfer(triMagSf);
315 
316  // Convert sumTriMagSf_ into cumulative sum of areas per proc
317  for (label i = 1; i < sumTriMagSf_.size(); i++)
318  {
319  sumTriMagSf_[i] += sumTriMagSf_[i-1];
320  }
321 
322  // Global patch area (over all processors)
323  patchArea_ = sumTriMagSf_.last();
324 
325  // Local patch bounds (this processor)
326  patchBounds_ = boundBox(patch.localPoints(), false);
327  patchBounds_.inflate(0.1);
328 
329  // Determine if all eddies spawned from a single processor
330  singleProc_ = patch.size() == returnReduce(patch.size(), sumOp<label>());
331  reduce(singleProc_, orOp<bool>());
332 }
333 
334 
335 void Foam::turbulentDFSEMInletFvPatchVectorField::initialiseEddyBox()
336 {
337  const scalarField& magSf = patch().magSf();
338 
339  //const scalarField cellDx(Foam::sqrt(magSf));
340  const scalarField cellDx(max(Foam::sqrt(magSf), 2/patch().deltaCoeffs()));
341 
342  // Inialise eddy box extents
343  forAll(*this, faceI)
344  {
345  scalar& s = sigmax_[faceI];
346 
347  // Length scale in x direction (based on eq. 14)
348  s = mag(L_[faceI]);
349  s = min(s, kappa_*delta_);
350 
351  // Allow eddies to be smaller than the mesh scale as suggested by
352  // the reference?
353  // s = min(s, nCellPerEddy_*cellDx[faceI]);
354  s = max(s, nCellPerEddy_*cellDx[faceI]);
355  }
356 
357  // Maximum extent across all processors
358  maxSigmaX_ = gMax(sigmax_);
359 
360  // Eddy box volume
361  v0_ = 2*gSum(magSf)*maxSigmaX_;
362 
363  if (debug)
364  {
365  Info<< "Patch: " << patch().patch().name() << " eddy box:" << nl
366  << " volume : " << v0_ << nl
367  << " maxSigmaX : " << maxSigmaX_ << nl
368  << endl;
369  }
370 }
371 
372 
373 Foam::pointIndexHit Foam::turbulentDFSEMInletFvPatchVectorField::setNewPosition
374 (
375  const bool global
376 )
377 {
378  // Initialise to miss
379  pointIndexHit pos(false, vector::max, -1);
380 
381  const polyPatch& patch = this->patch().patch();
382  const pointField& points = patch.points();
383 
384  if (global)
385  {
386  scalar areaFraction = rndGen_.globalPosition<scalar>(0, patchArea_);
387 
388  // Determine which processor to use
389  label procI = 0;
390  forAllReverse(sumTriMagSf_, i)
391  {
392  if (areaFraction >= sumTriMagSf_[i])
393  {
394  procI = i;
395  break;
396  }
397  }
398 
399  if (Pstream::myProcNo() == procI)
400  {
401  // Find corresponding decomposed face triangle
402  label triI = 0;
403  scalar offset = sumTriMagSf_[procI];
404  forAllReverse(triCumulativeMagSf_, i)
405  {
406  if (areaFraction > triCumulativeMagSf_[i] + offset)
407  {
408  triI = i;
409  break;
410  }
411  }
412 
413  // Find random point in triangle
414  const face& tf = triFace_[triI];
415  const triPointRef tri(points[tf[0]], points[tf[1]], points[tf[2]]);
416 
417  pos.setHit();
418  pos.setIndex(triToFace_[triI]);
419  pos.rawPoint() = tri.randomPoint(rndGen_);
420  }
421  }
422  else
423  {
424  // Find corresponding decomposed face triangle on local processor
425  label triI = 0;
426  scalar maxAreaLimit = triCumulativeMagSf_.last();
427  scalar areaFraction = rndGen_.position<scalar>(0, maxAreaLimit);
428 
429  forAllReverse(triCumulativeMagSf_, i)
430  {
431  if (areaFraction > triCumulativeMagSf_[i])
432  {
433  triI = i;
434  break;
435  }
436  }
437 
438  // Find random point in triangle
439  const face& tf = triFace_[triI];
440  const triPointRef tri(points[tf[0]], points[tf[1]], points[tf[2]]);
441 
442  pos.setHit();
443  pos.setIndex(triToFace_[triI]);
444  pos.rawPoint() = tri.randomPoint(rndGen_);
445  }
446 
447  return pos;
448 }
449 
450 
451 void Foam::turbulentDFSEMInletFvPatchVectorField::initialiseEddies()
452 {
453  DynamicList<eddy> eddies(size());
454 
455  // Initialise eddy properties
456  scalar sumVolEddy = 0;
457  scalar sumVolEddyAllProc = 0;
458 
459  while (sumVolEddyAllProc/v0_ < d_)
460  {
461  bool search = true;
462  label iter = 0;
463 
464  while (search && iter++ < seedIterMax_)
465  {
466  // Get new parallel consistent position
467  pointIndexHit pos(setNewPosition(true));
468  label faceI = pos.index();
469 
470  // Note: only 1 processor will pick up this face
471  if (faceI != -1)
472  {
473  eddy e
474  (
475  faceI,
476  pos.hitPoint(),
477  rndGen_.position<scalar>(-maxSigmaX_, maxSigmaX_),
478  sigmax_[faceI],
479  R_[faceI],
480  rndGen_
481  );
482 
483  // If eddy valid, patchFaceI is non-zero
484  if (e.patchFaceI() != -1)
485  {
486  eddies.append(e);
487  sumVolEddy += e.volume();
488  search = false;
489  }
490  }
491  // else eddy on remote processor
492 
493  reduce(search, andOp<bool>());
494  }
495 
496 
497  sumVolEddyAllProc = returnReduce(sumVolEddy, sumOp<scalar>());
498  }
499  eddies_.transfer(eddies);
500 
501  nEddy_ = eddies_.size();
502 
503  if (debug)
504  {
505  Pout<< "Patch:" << patch().patch().name();
506 
507  if (Pstream::parRun())
508  {
509  Pout<< " processor:" << Pstream::myProcNo();
510  }
511 
512  Pout<< " seeded:" << nEddy_ << " eddies" << endl;
513  }
514 
515  reduce(nEddy_, sumOp<label>());
516 
517  if (nEddy_ > 0)
518  {
519  Info<< "Turbulent DFSEM patch: " << patch().name()
520  << " seeded " << nEddy_ << " eddies with total volume "
521  << sumVolEddyAllProc
522  << endl;
523  }
524  else
525  {
527  << "Patch: " << patch().patch().name()
528  << " on field " << internalField().name()
529  << ": No eddies seeded - please check your set-up" << endl;
530  }
531 }
532 
533 
534 void Foam::turbulentDFSEMInletFvPatchVectorField::convectEddies
535 (
536  const scalar deltaT
537 )
538 {
539  // Note: all operations applied to local processor only
540 
541  label nRecycled = 0;
542 
543  forAll(eddies_, eddyI)
544  {
545  eddy& e = eddies_[eddyI];
546  e.move(deltaT*(UMean_ & patchNormal_));
547 
548  const scalar position0 = e.x();
549 
550  // Check to see if eddy has exited downstream box plane
551  if (position0 > maxSigmaX_)
552  {
553  bool search = true;
554  label iter = 0;
555 
556  while (search && iter++ < seedIterMax_)
557  {
558  // Spawn new eddy with new random properties (intensity etc)
559  pointIndexHit pos(setNewPosition(false));
560  label faceI = pos.index();
561 
562  e = eddy
563  (
564  faceI,
565  pos.hitPoint(),
566  position0 - floor(position0/maxSigmaX_)*maxSigmaX_,
567  sigmax_[faceI],
568  R_[faceI],
569  rndGen_
570  );
571 
572  if (e.patchFaceI() != -1)
573  {
574  search = false;
575  }
576  }
577 
578  nRecycled++;
579  }
580  }
581 
582  reduce(nRecycled, sumOp<label>());
583 
584  if (debug && nRecycled > 0)
585  {
586  Info<< "Patch: " << patch().patch().name() << " recycled "
587  << nRecycled << " eddies" << endl;
588  }
589 }
590 
591 
592 Foam::vector Foam::turbulentDFSEMInletFvPatchVectorField::uDashEddy
593 (
594  const List<eddy>& eddies,
595  const point& patchFaceCf
596 ) const
597 {
598  vector uDash(Zero);
599 
600  forAll(eddies, k)
601  {
602  const eddy& e = eddies[k];
603  uDash += e.uDash(patchFaceCf, patchNormal_);
604  }
605 
606  return uDash;
607 }
608 
609 
610 void Foam::turbulentDFSEMInletFvPatchVectorField::calcOverlappingProcEddies
611 (
612  List<List<eddy>>& overlappingEddies
613 ) const
614 {
615  int oldTag = UPstream::msgType();
616  UPstream::msgType() = oldTag + 1;
617 
618  List<boundBox> patchBBs(Pstream::nProcs());
619  patchBBs[Pstream::myProcNo()] = patchBounds_;
620  Pstream::gatherList(patchBBs);
621  Pstream::scatterList(patchBBs);
622 
623  // Per processor indices into all segments to send
624  List<DynamicList<label>> dynSendMap(Pstream::nProcs());
625 
626  forAll(eddies_, i)
627  {
628  // Collect overlapping eddies
629  const eddy& e = eddies_[i];
630 
631  // Eddy bounds
632  point x = e.position(patchNormal_);
633  boundBox ebb = e.bounds();
634  ebb.min() += x;
635  ebb.max() += x;
636 
637  forAll(patchBBs, procI)
638  {
639  // Not including intersection with local patch
640  if (procI != Pstream::myProcNo())
641  {
642  if (ebb.overlaps(patchBBs[procI]))
643  {
644  dynSendMap[procI].append(i);
645  }
646  }
647  }
648  }
649 
650  labelListList sendMap(Pstream::nProcs());
651  forAll(sendMap, procI)
652  {
653  sendMap[procI].transfer(dynSendMap[procI]);
654  }
655 
656  // Send the number of eddies for local processors to receive
657  labelListList sendSizes(Pstream::nProcs());
658  sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
659  forAll(sendMap, procI)
660  {
661  sendSizes[Pstream::myProcNo()][procI] = sendMap[procI].size();
662  }
663  Pstream::gatherList(sendSizes);
664  Pstream::scatterList(sendSizes);
665 
666  // Determine order of receiving
667  labelListList constructMap(Pstream::nProcs());
668 
669  // Local segment first
670  constructMap[Pstream::myProcNo()] = identity
671  (
672  sendMap[Pstream::myProcNo()].size()
673  );
674 
675  label segmentI = constructMap[Pstream::myProcNo()].size();
676  forAll(constructMap, procI)
677  {
678  if (procI != Pstream::myProcNo())
679  {
680  // What I need to receive is what other processor is sending to me
681  label nRecv = sendSizes[procI][Pstream::myProcNo()];
682  constructMap[procI].setSize(nRecv);
683 
684  for (label i = 0; i < nRecv; i++)
685  {
686  constructMap[procI][i] = segmentI++;
687  }
688  }
689  }
690 
691  mapDistribute map(segmentI, std::move(sendMap), std::move(constructMap));
692 
693  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
694 
695  for (const int domain : Pstream::allProcs())
696  {
697  const labelList& sendElems = map.subMap()[domain];
698 
699  if (domain != Pstream::myProcNo() && sendElems.size())
700  {
701  List<eddy> subEddies(UIndirectList<eddy>(eddies_, sendElems));
702 
703  UOPstream toDomain(domain, pBufs);
704 
705  toDomain<< subEddies;
706  }
707  }
708 
709  // Start receiving
710  pBufs.finishedSends();
711 
712  // Consume
713  for (const int domain : Pstream::allProcs())
714  {
715  const labelList& recvElems = map.constructMap()[domain];
716 
717  if (domain != Pstream::myProcNo() && recvElems.size())
718  {
719  UIPstream str(domain, pBufs);
720  {
721  str >> overlappingEddies[domain];
722  }
723  }
724  }
725 
726  // Restore tag
727  UPstream::msgType() = oldTag;
728 }
729 
730 
731 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
732 
735 (
736  const fvPatch& p,
738 )
739 :
741  delta_(Zero),
742  d_(Zero),
743  kappa_(Zero),
744 
745  perturb_(1e-5),
746  mapMethod_("nearestCell"),
747  mapperPtr_(nullptr),
748  interpolateR_(false),
749  interpolateL_(false),
750  interpolateU_(false),
751  R_(),
752  L_(),
753  U_(),
754  UMean_(Zero),
755 
756  patchArea_(-1),
757  triFace_(),
758  triToFace_(),
759  triCumulativeMagSf_(),
760  sumTriMagSf_(Pstream::nProcs() + 1, Zero),
761 
762  eddies_(Zero),
763  nCellPerEddy_(5),
764  patchNormal_(Zero),
765  v0_(Zero),
766  rndGen_(Pstream::myProcNo()),
767  sigmax_(size(), Zero),
768  maxSigmaX_(Zero),
769  nEddy_(Zero),
770  curTimeIndex_(-1),
771  patchBounds_(boundBox::invertedBox),
772  singleProc_(false),
773  writeEddies_(false)
774 {}
775 
776 
779 (
781  const fvPatch& p,
783  const fvPatchFieldMapper& mapper
784 )
785 :
786  fixedValueFvPatchField<vector>(ptf, p, iF, mapper),
787  delta_(ptf.delta_),
788  d_(ptf.d_),
789  kappa_(ptf.kappa_),
790 
791  perturb_(ptf.perturb_),
792  mapMethod_(ptf.mapMethod_),
793  mapperPtr_(nullptr),
794  interpolateR_(ptf.interpolateR_),
795  interpolateL_(ptf.interpolateL_),
796  interpolateU_(ptf.interpolateU_),
797  R_(ptf.R_, mapper),
798  L_(ptf.L_, mapper),
799  U_(ptf.U_, mapper),
800  UMean_(ptf.UMean_),
801 
802  patchArea_(ptf.patchArea_),
803  triFace_(ptf.triFace_),
804  triToFace_(ptf.triToFace_),
805  triCumulativeMagSf_(ptf.triCumulativeMagSf_),
806  sumTriMagSf_(ptf.sumTriMagSf_),
807 
808  eddies_(ptf.eddies_),
809  nCellPerEddy_(ptf.nCellPerEddy_),
810  patchNormal_(ptf.patchNormal_),
811  v0_(ptf.v0_),
812  rndGen_(ptf.rndGen_),
813  sigmax_(ptf.sigmax_, mapper),
814  maxSigmaX_(ptf.maxSigmaX_),
815  nEddy_(Zero),
816  curTimeIndex_(-1),
817  patchBounds_(ptf.patchBounds_),
818  singleProc_(ptf.singleProc_),
819  writeEddies_(ptf.writeEddies_)
820 {}
821 
822 
825 (
826  const fvPatch& p,
828  const dictionary& dict
829 )
830 :
832  delta_(dict.get<scalar>("delta")),
833  d_(dict.getOrDefault<scalar>("d", 1)),
834  kappa_(dict.getOrDefault<scalar>("kappa", 0.41)),
835 
836  perturb_(dict.getOrDefault<scalar>("perturb", 1e-5)),
837  mapMethod_(dict.getOrDefault<word>("mapMethod", "nearestCell")),
838  mapperPtr_(nullptr),
839  interpolateR_(dict.getOrDefault("interpolateR", false)),
840  interpolateL_(dict.getOrDefault("interpolateL", false)),
841  interpolateU_(dict.getOrDefault("interpolateU", false)),
842  R_(interpolateOrRead<symmTensor>("R", dict, interpolateR_)),
843  L_(interpolateOrRead<scalar>("L", dict, interpolateL_)),
844  U_(interpolateOrRead<vector>("U", dict, interpolateU_)),
845  UMean_(Zero),
846 
847  patchArea_(-1),
848  triFace_(),
849  triToFace_(),
850  triCumulativeMagSf_(),
851  sumTriMagSf_(Pstream::nProcs() + 1, Zero),
852 
853  eddies_(),
854  nCellPerEddy_(dict.getOrDefault<label>("nCellPerEddy", 5)),
855  patchNormal_(Zero),
856  v0_(Zero),
857  rndGen_(),
858  sigmax_(size(), Zero),
859  maxSigmaX_(Zero),
860  nEddy_(Zero),
861  curTimeIndex_(-1),
862  patchBounds_(boundBox::invertedBox),
863  singleProc_(false),
864  writeEddies_(dict.getOrDefault("writeEddies", false))
865 {
866  eddy::debug = debug;
867 
868  checkStresses(R_);
869 
870  // Set UMean as patch area average value
871  UMean_ = gSum(U_*patch().magSf())/(gSum(patch().magSf()) + ROOTVSMALL);
872 }
873 
874 
877 (
879 )
880 :
882  delta_(ptf.delta_),
883  d_(ptf.d_),
884  kappa_(ptf.kappa_),
885 
886  perturb_(ptf.perturb_),
887  mapMethod_(ptf.mapMethod_),
888  mapperPtr_(nullptr),
889  interpolateR_(ptf.interpolateR_),
890  interpolateL_(ptf.interpolateL_),
891  interpolateU_(ptf.interpolateU_),
892  R_(ptf.R_),
893  L_(ptf.L_),
894  U_(ptf.U_),
895  UMean_(ptf.UMean_),
896 
897  patchArea_(ptf.patchArea_),
898  triFace_(ptf.triFace_),
899  triToFace_(ptf.triToFace_),
900  triCumulativeMagSf_(ptf.triCumulativeMagSf_),
901  sumTriMagSf_(ptf.sumTriMagSf_),
902 
903  eddies_(ptf.eddies_),
904  nCellPerEddy_(ptf.nCellPerEddy_),
905  patchNormal_(ptf.patchNormal_),
906  v0_(ptf.v0_),
907  rndGen_(ptf.rndGen_),
908  sigmax_(ptf.sigmax_),
909  maxSigmaX_(ptf.maxSigmaX_),
910  nEddy_(Zero),
911  curTimeIndex_(-1),
912  patchBounds_(ptf.patchBounds_),
913  singleProc_(ptf.singleProc_),
914  writeEddies_(ptf.writeEddies_)
915 {}
916 
917 
920 (
923 )
924 :
926  delta_(ptf.delta_),
927  d_(ptf.d_),
928  kappa_(ptf.kappa_),
929 
930  perturb_(ptf.perturb_),
931  mapMethod_(ptf.mapMethod_),
932  mapperPtr_(nullptr),
933  interpolateR_(ptf.interpolateR_),
934  interpolateL_(ptf.interpolateL_),
935  interpolateU_(ptf.interpolateU_),
936  R_(ptf.R_),
937  L_(ptf.L_),
938  U_(ptf.U_),
939  UMean_(ptf.UMean_),
940 
941  patchArea_(ptf.patchArea_),
942  triFace_(ptf.triFace_),
943  triToFace_(ptf.triToFace_),
944  triCumulativeMagSf_(ptf.triCumulativeMagSf_),
945  sumTriMagSf_(ptf.sumTriMagSf_),
946 
947  eddies_(ptf.eddies_),
948  nCellPerEddy_(ptf.nCellPerEddy_),
949  patchNormal_(ptf.patchNormal_),
950  v0_(ptf.v0_),
951  rndGen_(ptf.rndGen_),
952  sigmax_(ptf.sigmax_),
953  maxSigmaX_(ptf.maxSigmaX_),
954  nEddy_(Zero),
955  curTimeIndex_(-1),
956  patchBounds_(ptf.patchBounds_),
957  singleProc_(ptf.singleProc_),
958  writeEddies_(ptf.writeEddies_)
959 {}
960 
961 
962 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
963 
965 (
966  const symmTensorField& Rf
967 )
968 {
969  // Perform checks of the stress tensor based on Cholesky decomposition
970  // constraints
971 
972  forAll(Rf, facei)
973  {
974  const symmTensor& R = Rf[facei];
975 
976  if (R.xx() <= 0)
977  {
979  << "Reynolds stress " << R << " at face " << facei
980  << " does not obey the constraint: R_xx > 0"
981  << exit(FatalError);
982  }
983 
984  scalar a_xx = sqrt(R.xx());
985 
986  scalar a_xy = R.xy()/a_xx;
987 
988  scalar a_yy_2 = R.yy() - sqr(a_xy);
989 
990  if (a_yy_2 < 0)
991  {
993  << "Reynolds stress " << R << " at face " << facei
994  << " leads to an invalid Cholesky decomposition due to the "
995  << "constraint R_yy - sqr(a_xy) >= 0"
996  << exit(FatalError);
997  }
998 
999  scalar a_yy = Foam::sqrt(a_yy_2);
1000 
1001  scalar a_xz = R.xz()/a_xx;
1002 
1003  scalar a_yz = (R.yz() - a_xy*a_xz)*a_yy;
1004 
1005  scalar a_zz_2 = R.zz() - sqr(a_xz) - sqr(a_yz);
1006 
1007  if (a_zz_2 < 0)
1008  {
1010  << "Reynolds stress " << R << " at face " << facei
1011  << " leads to an invalid Cholesky decomposition due to the "
1012  << "constraint R_zz - sqr(a_xz) - sqr(a_yz) >= 0"
1013  << exit(FatalError);
1014  }
1015 
1016  scalar a_zz = Foam::sqrt(a_zz_2);
1017 
1018  if (debug)
1019  {
1020  Pout<< "R: " << R
1021  << " a_xx:" << a_xx << " a_xy:" << a_xy << " a_xz:" << a_xy
1022  << " a_yy:" << a_yy << " a_yz:" << a_yz
1023  << " a_zz:" << a_zz
1024  << endl;
1025  }
1026  }
1027 
1028  return true;
1029 }
1030 
1031 
1034  const fvPatchFieldMapper& m
1035 )
1036 {
1038 
1039  // Clear interpolator
1040  mapperPtr_.clear();
1041  R_.autoMap(m);
1042  L_.autoMap(m);
1043  U_.autoMap(m);
1044 
1045  sigmax_.autoMap(m);
1046 }
1047 
1048 
1051  const fvPatchVectorField& ptf,
1052  const labelList& addr
1053 )
1054 {
1056 
1057  const turbulentDFSEMInletFvPatchVectorField& dfsemptf =
1058  refCast<const turbulentDFSEMInletFvPatchVectorField>(ptf);
1059 
1060  R_.rmap(dfsemptf.R_, addr);
1061  L_.rmap(dfsemptf.L_, addr);
1062  U_.rmap(dfsemptf.U_, addr);
1063 
1064  // Clear interpolator
1065  mapperPtr_.clear();
1066 
1067  sigmax_.rmap(dfsemptf.sigmax_, addr);
1068 }
1069 
1070 
1072 {
1073  if (updated())
1074  {
1075  return;
1076  }
1077 
1078  if (curTimeIndex_ == -1)
1079  {
1080  initialisePatch();
1081 
1082  initialiseEddyBox();
1083 
1084  initialiseEddies();
1085  }
1086 
1087 
1088  if (curTimeIndex_ != db().time().timeIndex())
1089  {
1090  if (debug)
1091  {
1092  label n = eddies_.size();
1093  Info<< "Number of eddies: " << returnReduce(n, sumOp<label>())
1094  << endl;
1095  }
1096 
1097  const scalar deltaT = db().time().deltaTValue();
1098 
1099  // Move eddies using mean velocity
1100  convectEddies(deltaT);
1101 
1102  // Set velocity
1103  vectorField& U = *this;
1104  //U = UMean_;
1105  U = U_;
1106 
1107  const pointField& Cf = patch().Cf();
1108 
1109  // Apply second part of normalisation coefficient
1110  // Note: factor of 2 required to match reference stresses?
1111  const scalar FACTOR = 2;
1112  const scalar c = FACTOR*Foam::sqrt(10*v0_)/Foam::sqrt(scalar(nEddy_));
1113 
1114  // In parallel, need to collect all eddies that will interact with
1115  // local faces
1116 
1117  if (singleProc_ || !Pstream::parRun())
1118  {
1119  forAll(U, faceI)
1120  {
1121  U[faceI] += c*uDashEddy(eddies_, Cf[faceI]);
1122  }
1123  }
1124  else
1125  {
1126  // Process local eddy contributions
1127  forAll(U, faceI)
1128  {
1129  U[faceI] += c*uDashEddy(eddies_, Cf[faceI]);
1130  }
1131 
1132  // Add contributions from overlapping eddies
1133  List<List<eddy>> overlappingEddies(Pstream::nProcs());
1134  calcOverlappingProcEddies(overlappingEddies);
1135 
1136  forAll(overlappingEddies, procI)
1137  {
1138  const List<eddy>& eddies = overlappingEddies[procI];
1139 
1140  if (eddies.size())
1141  {
1142  //Pout<< "Applying " << eddies.size()
1143  // << " eddies from processor " << procI << endl;
1144 
1145  forAll(U, faceI)
1146  {
1147  U[faceI] += c*uDashEddy(eddies, Cf[faceI]);
1148  }
1149  }
1150  }
1151  }
1152 
1153  // Re-scale to ensure correct flow rate
1154  scalar fCorr =
1155  gSum((UMean_ & patchNormal_)*patch().magSf())
1156  /gSum(U & -patch().Sf());
1157 
1158  U *= fCorr;
1159 
1160  if (debug)
1161  {
1162  Info<< "Patch:" << patch().patch().name()
1163  << " min/max(U):" << gMin(U) << ", " << gMax(U) << endl;
1164  }
1165 
1166  curTimeIndex_ = db().time().timeIndex();
1167 
1168  if (writeEddies_)
1169  {
1170  writeEddyOBJ();
1171  }
1172 
1173  if (debug && db().time().writeTime())
1174  {
1175  writeLumleyCoeffs();
1176  }
1177  }
1178 
1179  fixedValueFvPatchVectorField::updateCoeffs();
1180 }
1181 
1182 
1184 {
1186  writeEntry("value", os);
1187  os.writeEntry("delta", delta_);
1188  os.writeEntryIfDifferent<scalar>("d", 1.0, d_);
1189  os.writeEntryIfDifferent<scalar>("kappa", 0.41, kappa_);
1190  os.writeEntryIfDifferent<scalar>("perturb", 1e-5, perturb_);
1191  os.writeEntryIfDifferent<label>("nCellPerEddy", 5, nCellPerEddy_);
1192  os.writeEntryIfDifferent("writeEddies", false, writeEddies_);
1193 
1194  if (!interpolateR_)
1195  {
1196  R_.writeEntry("R", os);
1197  }
1198 
1199  if (!interpolateL_)
1200  {
1201  L_.writeEntry("L", os);
1202  }
1203 
1204  if (!interpolateU_)
1205  {
1206  U_.writeEntry("U", os);
1207  }
1208 
1209  if (!mapMethod_.empty())
1210  {
1212  (
1213  "mapMethod",
1214  "nearestCell",
1215  mapMethod_
1216  );
1217  }
1218 }
1219 
1220 
1221 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1222 
1223 namespace Foam
1224 {
1226  (
1229  );
1230 }
1231 
1232 
1233 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::fvPatchField< vector >
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
volFields.H
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::fvPatchField::write
virtual void write(Ostream &) const
Write.
Definition: fvPatchField.C:364
Foam::Ostream::writeEntryIfDifferent
Ostream & writeEntryIfDifferent(const word &key, const T &value1, const T &value2)
Write a keyword/value entry only when the two values differ.
Definition: Ostream.H:244
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::turbulentDFSEMInletFvPatchVectorField::checkStresses
static bool checkStresses(const symmTensorField &Rf)
Helper function to check that Reynold stresses are valid.
Definition: turbulentDFSEMInletFvPatchVectorField.C:965
Foam::SymmTensor< scalar >
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::UPstream::commsTypes::nonBlocking
Foam::eddy::debug
static int debug
Definition: eddy.H:143
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
rawIOField.H
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
s
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;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::invariantIII
Cmpt invariantIII(const SymmTensor< Cmpt > &st)
Return the 3rd invariant of a SymmTensor.
Definition: SymmTensorI.H:362
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
momentOfInertia.H
Foam::gAverage
Type gAverage(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:604
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Definition: gatherScatterList.C:215
globalIndex.H
Foam::boundBox::invertedBox
static const boundBox invertedBox
A large inverted boundBox: min/max == +/- ROOTVGREAT.
Definition: boundBox.H:86
Foam::UPstream::parRun
static bool & parRun()
Test if this a parallel run, or allow modify access.
Definition: UPstream.H:434
Foam::pointToPointPlanarInterpolation
Interpolates between two sets of unstructured points using 2D Delaunay triangulation....
Definition: pointToPointPlanarInterpolation.H:53
Foam::turbulentDFSEMInletFvPatchVectorField::write
virtual void write(Ostream &) const
Write.
Definition: turbulentDFSEMInletFvPatchVectorField.C:1183
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:182
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
fvPatchFieldMapper.H
Foam::gSum
Type gSum(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:594
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:81
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::turbulentDFSEMInletFvPatchVectorField::turbulentDFSEMInletFvPatchVectorField
turbulentDFSEMInletFvPatchVectorField(const fvPatch &, const DimensionedField< vector, volMesh > &)
Construct from patch and internal field.
Definition: turbulentDFSEMInletFvPatchVectorField.C:735
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::sumOp
Definition: ops.H:213
Foam::fixedValueFvPatchField
This boundary condition supplies a fixed value constraint, and is the base class for a number of othe...
Definition: fixedValueFvPatchField.H:80
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
OFstream.H
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
R
#define R(A, B, C, D, E, F, K, M)
Foam::PointIndexHit
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:52
turbulentDFSEMInletFvPatchVectorField.H
Foam::Field< symmTensor >
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
DebugInFunction
#define DebugInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:365
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::fvPatch
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:65
Foam::symmTensor
SymmTensor< scalar > symmTensor
SymmTensor of scalars, i.e. SymmTensor<scalar>.
Definition: symmTensor.H:59
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::fvPatchField::rmap
virtual void rmap(const fvPatchField< Type > &, const labelList &)
Reverse map the given fvPatchField onto this fvPatchField.
Definition: fvPatchField.C:303
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::invariantII
Cmpt invariantII(const SymmTensor< Cmpt > &st)
Return the 2nd invariant of a SymmTensor.
Definition: SymmTensorI.H:350
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::turbulentDFSEMInletFvPatchVectorField::rmap
virtual void rmap(const fvPatchVectorField &ptf, const labelList &addr)
Reverse map the given fvPatchField onto this fvPatchField.
Definition: turbulentDFSEMInletFvPatchVectorField.C:1050
Foam::Pstream::listCombineGather
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:290
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
U
U
Definition: pEqn.H:72
Foam::UPstream::msgType
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:541
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::UPstream::allProcs
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:509
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
A PointIndexHit for 3D points.
Definition: pointIndexHit.H:46
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:464
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::VectorSpace< Vector< Cmpt >, Cmpt, 3 >::max
static const Vector< Cmpt > max
Definition: VectorSpace.H:117
f
labelList f(nPoints)
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::Vector< scalar >
Foam::List< label >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::token::TAB
Tab [isspace].
Definition: token.H:118
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::turbulentDFSEMInletFvPatchVectorField
Velocity boundary condition including synthesised eddies for use with LES and DES turbulent flows.
Definition: turbulentDFSEMInletFvPatchVectorField.H:179
points
const pointField & points
Definition: gmvOutputHeader.H:1
k
label k
Boltzmann constant.
Definition: LISASMDCalcMethod2.H:41
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::search
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:576
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:232
Foam::turbulentDFSEMInletFvPatchVectorField::updateCoeffs
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
Definition: turbulentDFSEMInletFvPatchVectorField.C:1071
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
forAllReverse
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:309
Foam::turbulentDFSEMInletFvPatchVectorField::autoMap
virtual void autoMap(const fvPatchFieldMapper &m)
Map (and resize as needed) from self given a mapping object.
Definition: turbulentDFSEMInletFvPatchVectorField.C:1033
Foam::fvPatchFieldMapper
Foam::fvPatchFieldMapper.
Definition: fvPatchFieldMapper.H:47
timeIndex
label timeIndex
Definition: getTimeIndex.H:4
Foam::tr
dimensionedScalar tr(const dimensionedSphericalTensor &dt)
Definition: dimensionedSphericalTensor.C:51
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::makePatchTypeField
makePatchTypeField(fvPatchScalarField, atmBoundaryLayerInletEpsilonFvPatchScalarField)
Foam::gMin
Type gMin(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:593
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:432
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::cbrt
dimensionedScalar cbrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:155
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:122
constant
constant condensation/saturation model.
triFace
face triFace(3)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:303
Foam::fvPatchField::autoMap
virtual void autoMap(const fvPatchFieldMapper &)
Map (and resize as needed) from self given a mapping object.
Definition: fvPatchField.C:240
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Number of processes in parallel run, and 1 for serial run.
Definition: UPstream.H:446
Foam::DimensionedField
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: DimensionedField.H:54
Foam::triPointRef
triangle< point, const point & > triPointRef
A triangle using referred points.
Definition: triangle.H:73
Foam::IOobject::MUST_READ
Definition: IOobject.H:120
Foam::dev
dimensionedSymmTensor dev(const dimensionedSymmTensor &dt)
Definition: dimensionedSymmTensor.C:106
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177