eddy.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-2021 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 
29 #include "eddy.H"
30 #include "mathematicalConstants.H"
31 
32 using namespace Foam::constant;
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 Foam::label Foam::eddy::Gamma2Values[] = {1, 2, 3, 4, 5, 6, 7, 8};
37 Foam::UList<Foam::label> Foam::eddy::Gamma2(&Gamma2Values[0], 8);
38 int Foam::eddy::debug = 0;
39 
40 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 
42 bool Foam::eddy::setScales
43 (
44  const scalar sigmaX,
45  const label gamma2,
46  const vector& e,
47  const vector& lambda,
48  vector& sigma,
49  vector& alpha
50 ) const
51 {
52  // Static array of gamma^2 vs c2 coefficient (PCR:Table 1)
53  static const scalar gamma2VsC2[8] =
54  {2, 1.875, 1.737, 1.75, 0.91, 0.825, 0.806, 1.5};
55 
56  const scalar gamma = Foam::sqrt(scalar(gamma2));
57 
58  // c2 coefficient retrieved from array
59  const scalar c2 = gamma2VsC2[gamma2 - 1];
60 
61  // Length scale in the largest eigenvalue direction
62  const label d1 = dir1_;
63  const label d2 = (d1 + 1) % 3;
64  const label d3 = (d1 + 2) % 3;
65 
66  sigma[d1] = sigmaX;
67 
68  // Note: sigma_average = 1/3*(sigma_x + sigma_y + sigma_z)
69  // Substituting for sigma_y = sigma_x/gamma and sigma_z = sigma_y
70  // Other length scales equal, as function of major axis length and gamma
71  sigma[d2] = sigma[d1]/gamma;
72  sigma[d3] = sigma[d2];
73 
74  // (PCR:Eq. 13)
75  const vector sigma2(cmptMultiply(sigma, sigma));
76  const scalar slos2 = cmptSum(cmptDivide(lambda, sigma2));
77 
78  bool ok = true;
79 
80  for (label beta = 0; beta < vector::nComponents; ++beta)
81  {
82  const scalar x = slos2 - 2*lambda[beta]/sigma2[beta];
83 
84  if (x < 0)
85  {
86  alpha[beta] = 0;
87  ok = false;
88  }
89  else
90  {
91  // (SST:Eq. 23)
92  alpha[beta] = e[beta]*sqrt(x/(2*c2));
93  }
94  }
95 
96  if (debug > 1)
97  {
98  Pout<< "c2:" << c2
99  << ", gamma2:" << gamma2
100  << ", gamma:" << gamma
101  << ", lambda:" << lambda
102  << ", sigma2: " << sigma2
103  << ", slos2: " << slos2
104  << ", sigmaX:" << sigmaX
105  << ", sigma:" << sigma
106  << ", alpha:" << alpha
107  << endl;
108  }
109 
110  return ok;
111 }
112 
113 
114 // * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * //
115 
117 :
118  patchFaceI_(-1),
119  position0_(Zero),
120  x_(0),
121  sigma_(Zero),
122  alpha_(Zero),
123  Rpg_(tensor::I),
124  c1_(-1),
125  dir1_(0)
126 {}
127 
128 
130 (
131  const label patchFaceI,
132  const point& position0,
133  const scalar x,
134  const scalar sigmaX,
135  const symmTensor& R,
136  Random& rndGen
137 )
138 :
139  patchFaceI_(patchFaceI),
140  position0_(position0),
141  x_(x),
142  sigma_(Zero),
143  alpha_(Zero),
144  Rpg_(tensor::I),
145  c1_(-1),
146  dir1_(0)
147 {
148  // Principal stresses - eigenvalues returned in ascending order
149  const vector lambda(eigenValues(R));
150 
151  // Eddy rotation from principal-to-global axes
152  // - given by the 3 eigenvectors of the Reynold stress tensor as rows in
153  // the result tensor (transposed transformation tensor)
154  // - returned in ascending eigenvalue order
155  Rpg_ = eigenVectors(R, lambda).T();
156 
157  if (debug)
158  {
159  // Global->Principal transform = Rgp = Rpg.T()
160  // Rgp & R & Rgp.T() should have eigenvalues on its diagonal and
161  // zeros for all other components
162  Pout<< "Rpg.T() & R & Rpg: " << (Rpg_.T() & R & Rpg_) << endl;
163  }
164 
165  // Set the eddy orientation to position of max eigenvalue
166  // (direction of eddy major axis, sigma_x in reference)
167  dir1_ = 2;
168 
169  // Random vector of 1's and -1's
170  const vector e(epsilon(rndGen));
171 
172  // Set intensities and length scales
173  bool found = false;
174  forAll(Gamma2, i)
175  {
176  // Random length scale ratio, gamma = sigmax/sigmay = sigmax/sigmaz
177  // - using gamma^2 to ease lookup of c2 coefficient
178  const label gamma2 = Gamma2[i];
179 
180  if (setScales(sigmaX, gamma2, e, lambda, sigma_, alpha_))
181  {
182  found = true;
183  break;
184  }
185  }
186 
187  // Normalisation coefficient (PCR:Eq. 11)
188  // Note: sqrt(10*V)/sqrt(nEddy) applied outside when computing uPrime
189  c1_ = cmptAv(sigma_)/cmptProduct(sigma_)*cmptMin(sigma_);
190 
191  if (found)
192  {
193  // Shuffle the gamma^2 values
194  rndGen.shuffle(Gamma2);
195  }
196  else
197  {
198  if (debug)
199  {
200  // If not found typically means that the stress has a repeated
201  // eigenvalue/not covered by the selection of Gamma values, e.g.
202  // as seen by range of applicability on Lumley diagram
204  << "Unable to set eddy intensity for eddy: " << *this
205  << endl;
206  }
207 
208  // Remove the influence of this eddy/indicate that its initialisation
209  // failed
210  patchFaceI_ = -1;
211  }
212 }
213 
214 
216 :
217  patchFaceI_(e.patchFaceI_),
218  position0_(e.position0_),
219  x_(e.x_),
220  sigma_(e.sigma_),
221  alpha_(e.alpha_),
222  Rpg_(e.Rpg_),
223  c1_(e.c1_),
224  dir1_(e.dir1_)
225 {}
226 
227 
228 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
229 
230 Foam::vector Foam::eddy::uPrime(const point& xp, const vector& n) const
231 {
232  // Relative position inside eddy (global system) (PCR:p. 524)
233  const vector r(cmptDivide(xp - position(n), sigma_));
234 
235  if (mag(r) >= scalar(1))
236  {
237  return vector::zero;
238  }
239 
240  // Relative position inside eddy (eddy principal system)
241  const vector rp(Rpg_.T() & r);
242 
243  // Shape function (eddy principal system)
244  const vector q(cmptMultiply(sigma_, vector::one - cmptMultiply(rp, rp)));
245 
246  // Fluctuating velocity (eddy principal system) (PCR:Eq. 8)
247  const vector uPrimep(cmptMultiply(q, rp^alpha_));
248 
249  // Convert into global system (PCR:Eq. 10)
250  return c1_*(Rpg_ & uPrimep);
251 }
252 
253 
255 (
256  const vector& n,
257  Ostream& os
258 ) const
259 {
260  const point p(position(n));
261  os << "v " << p.x() << " " << p.y() << " " << p.z() << nl;
262 }
263 
264 
265 Foam::label Foam::eddy::writeSurfaceOBJ
266 (
267  const label pointOffset,
268  const vector& n,
269  Ostream& os
270 ) const
271 {
272  if (patchFaceI_ < 0)
273  {
274  // Invalid eddy
275  return 0;
276  }
277 
278  static const label nFaceAxis = 20;
279  static const label nFaceTheta = 22;
280  static const label nEddyPoints = (nFaceAxis - 1)*nFaceTheta + 2;
282 
283  static scalar dTheta = mathematical::twoPi/nFaceTheta;
284  static scalar dPhi = mathematical::pi/scalar(nFaceAxis);
285 
286  label pointI = pointOffset;
287 
288  const vector& s = sigma_;
289 
290  const vector axisDir = tensor::I.vectorComponent(dir1_);
291  const label dir2 = (dir1_ + 1) % 3;
292  const label dir3 = (dir1_ + 2) % 3;
293 
294  // Calculate the point positions
295  x[0] = axisDir*s[dir1_];
296  x[nEddyPoints - 1] = - axisDir*s[dir1_];
297 
298  label eddyPtI = 1;
299  for (label axisI = 1; axisI < nFaceAxis; ++axisI)
300  {
301  const scalar z = s[dir1_]*cos(axisI*dPhi);
302  const scalar r = sqrt(sqr(s[dir2])*(1 - sqr(z)/sqr(s[dir1_])));
303 
304  for (label thetaI = 0; thetaI < nFaceTheta; ++thetaI)
305  {
306  const scalar theta = thetaI*dTheta;
307  point& p = x[eddyPtI++];
308  p[dir1_] = z;
309  p[dir2] = r*sin(theta);
310  p[dir3] = r*cos(theta);
311  }
312  }
313 
314  // Write points
315  forAll(x, i)
316  {
317  const point p = position(n) + (Rpg_ & x[i]);
318  os << "v " << p.x() << " " << p.y() << " " << p.z() << nl;
319  }
320 
321  // Write the end cap tri faces
322  for (label faceI = 0; faceI < nFaceTheta; ++faceI)
323  {
324  const label p1 = pointI + 1;
325  const label p2 = p1 + faceI + 1;
326  label p3 = p2 + 1;
327  if (faceI == nFaceTheta - 1) p3 -= nFaceTheta;
328  os << "f " << p1 << " " << p2 << " " << p3 << nl;
329 
330  const label q1 = pointI + nEddyPoints;
331  const label q2 = q1 - faceI - 1;
332  label q3 = q2 - 1;
333  if (faceI == nFaceTheta - 1) q3 += nFaceTheta;
334  os << "f " << q1 << " " << q2 << " " << q3 << nl;
335  }
336 
337  // Write quad faces
338  for (label axisI = 1; axisI < nFaceAxis - 1; ++axisI)
339  {
340  for (label thetaI = 0; thetaI < nFaceTheta; ++thetaI)
341  {
342  const label p1 = pointI + 1 + (axisI - 1)*nFaceTheta + thetaI + 1;
343  const label p2 = p1 + nFaceTheta;
344  label p3 = p2 + 1;
345  label p4 = p1 + 1;
346 
347  if (thetaI == nFaceTheta - 1)
348  {
349  p3 -= nFaceTheta;
350  p4 -= nFaceTheta;
351  }
352  os << "f " << p1 << " " << p2 << " " << p3 << " " << p4 << nl;
353  }
354  }
355 
356  return nEddyPoints;
357 }
358 
359 
360 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::Random
Random number generator.
Definition: Random.H:59
Foam::Tensor< scalar >
mathematicalConstants.H
Foam::SymmTensor< scalar >
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::one
static const Vector< scalar > one
Definition: VectorSpace.H:116
rp
regionProperties rp(runTime)
Foam::eddy::debug
static int debug
Flag to activate debug statements.
Definition: eddy.H:147
Gamma2Values
Foam::UList< Foam::label > Foam::eddy::Gamma2 &[0] Gamma2Values
Definition: eddy.C:37
Foam::Tensor::I
static const Tensor I
Definition: Tensor.H:85
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::eddy::writeCentreOBJ
void writeCentreOBJ(const vector &n, Ostream &os) const
Write the eddy centre in OBJ format.
Definition: eddy.C:255
Foam::cmptMultiply
dimensioned< Type > cmptMultiply(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::eigenValues
dimensionedVector eigenValues(const dimensionedSymmTensor &dt)
Definition: dimensionedTensor.C:149
Foam::constant
Different types of constants.
Definition: atomicConstants.C:38
Foam::constant::atomic::alpha
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Definition: readThermalProperties.H:212
Foam::sin
dimensionedScalar sin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:264
Foam::eigenVectors
dimensionedTensor eigenVectors(const dimensionedSymmTensor &dt)
Definition: dimensionedTensor.C:160
Foam::cmptProduct
Cmpt cmptProduct(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:596
Foam::Random::shuffle
void shuffle(UList< Type > &values)
Shuffle the values in the list.
Definition: RandomTemplates.C:83
Foam::eddy
Class to describe eddies for the turbulentDFSEMInletFvPatchVectorField boundary condition.
Definition: eddy.H:69
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::dimensioned::T
dimensioned< Type > T() const
Return transpose.
Definition: dimensionedSphericalTensor.C:38
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::eddy::writeSurfaceOBJ
label writeSurfaceOBJ(const label pointOffset, const vector &n, Ostream &os) const
Write the eddy surface in OBJ format.
Definition: eddy.C:266
Foam::cmptMin
void cmptMin(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:302
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::eddy::eddy
eddy()
Construct null.
Definition: eddy.C:116
R
#define R(A, B, C, D, E, F, K, M)
beta
dimensionedScalar beta("beta", dimless/dimTemperature, laminarTransport)
Foam::cmptAv
tmp< DimensionedField< typename DimensionedField< Type, GeoMesh >::cmptType, GeoMesh >> cmptAv(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:246
Foam::Tensor::vectorComponent
Vector< Cmpt > vectorComponent(const direction cmpt) const
Deprecated(2018-12) Return vector for given row (0,1)
Definition: Tensor.H:316
eddy.H
Foam::constant::mathematical::twoPi
constexpr scalar twoPi(2 *M_PI)
lambda
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
os
OBJstream os(runTime.globalPath()/outputName)
Foam::cmptSum
Cmpt cmptSum(const SphericalTensor< Cmpt > &st)
Return the sum of components of a SphericalTensor.
Definition: SphericalTensorI.H:164
Foam::constant::physicoChemical::c2
const dimensionedScalar c2
Second radiation constant: default SI units: [m.K].
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::cmptDivide
dimensioned< Type > cmptDivide(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::constant::mathematical::pi
constexpr scalar pi(M_PI)
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::Vector< scalar >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::FixedList
A 1D vector of objects of type <T> with a fixed length <N>.
Definition: HashTable.H:104
gamma
const scalar gamma
Definition: EEqn.H:9
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
x
x
Definition: LISASMDCalcMethod2.H:52
rndGen
Random rndGen
Definition: createFields.H:23
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::zero
static const Vector< scalar > zero
Definition: VectorSpace.H:115
epsilon
scalar epsilon
Definition: evaluateNearWall.H:7
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
sigma
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
Foam::eddy::uPrime
vector uPrime(const point &xp, const vector &n) const
Return the fluctuating velocity contribution at local point xp.
Definition: eddy.C:230
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::nComponents
static constexpr direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:101
Foam::I
static const Identity< scalar > I
Definition: Identity.H:95
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265