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-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 
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
53  static const scalar gamma2VsC2[8] =
54  {2, 1.875, 1.737, 1.75, 0.91, 0.825, 0.806, 1.5};
55 
56  scalar gamma = Foam::sqrt(scalar(gamma2));
57 
58  // c2 coefficient retrieved from array
59  scalar c2 = gamma2VsC2[gamma2 - 1];
60 
61  // Length scale in largest eigenvalue direction
62  label d1 = dir1_;
63  label d2 = (d1 + 1) % 3;
64  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  //sigma[d1] = 3*sigmaX/(1 + 2/gamma);
71  // Other length scales equal, as function of major axis length and gamma
72  sigma[d2] = sigma[d1]/gamma;
73  sigma[d3] = sigma[d2];
74 
75  vector sigma2 = cmptMultiply(sigma, sigma);
76  scalar slos2 = cmptSum(cmptDivide(lambda, sigma2));
77 
78  bool ok = true;
79 
80  for (label beta = 0; beta < 3; ++beta)
81  {
82  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  alpha[beta] = e[beta]*sqrt(x/(2*c2));
92  }
93  }
94 
95  if (debug > 1)
96  {
97  Pout<< "c2:" << c2
98  << ", gamma2:" << gamma2
99  << ", gamma:" << gamma
100  << ", lambda:" << lambda
101  << ", sigma2: " << sigma2
102  << ", slos2: " << slos2
103  << ", sigmaX:" << sigmaX
104  << ", sigma:" << sigma
105  << ", alpha:" << alpha
106  << endl;
107  }
108 
109  return ok;
110 }
111 
112 
113 // * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * //
114 
116 :
117  patchFaceI_(-1),
118  position0_(Zero),
119  x_(0),
120  sigma_(Zero),
121  alpha_(Zero),
122  Rpg_(tensor::I),
123  c1_(-1),
124  dir1_(0)
125 {}
126 
127 
129 (
130  const label patchFaceI,
131  const point& position0,
132  const scalar x,
133  const scalar sigmaX,
134  const symmTensor& R,
135  Random& rndGen
136 )
137 :
138  patchFaceI_(patchFaceI),
139  position0_(position0),
140  x_(x),
141  sigma_(Zero),
142  alpha_(Zero),
143  Rpg_(tensor::I),
144  c1_(-1),
145  dir1_(0)
146 {
147  // Principal stresses - eigenvalues returned in ascending order
149 
150  // Eddy rotation from principal-to-global axes
151  // - given by the 3 eigenvectors of the Reynold stress tensor as rows in
152  // the result tensor (transposed transformation tensor)
153  // - returned in ascending eigenvalue order
154  Rpg_ = eigenVectors(R, lambda).T();
155 
156  if (debug)
157  {
158  // Global->Principal transform = Rgp = Rpg.T()
159  // Rgp & R & Rgp.T() should have eigenvalues on its diagonal and
160  // zeros for all other components
161  Pout<< "Rpg.T() & R & Rpg: " << (Rpg_.T() & R & Rpg_) << endl;
162  }
163 
164  // Set the eddy orientation to position of max eigenvalue
165  // (direction of eddy major axis, sigma_x in reference)
166  dir1_ = 2;
167 
168  // Random vector of 1's and -1's
169  const vector e(epsilon(rndGen));
170 
171  // Set intensities and length scales
172  bool found = false;
173  forAll(Gamma2, i)
174  {
175  // Random length scale ratio, gamma = sigmax/sigmay = sigmax/sigmaz
176  // - using gamma^2 to ease lookup of c2 coefficient
177  label g2 = Gamma2[i];
178 
179  if (setScales(sigmaX, g2, e, lambda, sigma_, alpha_))
180  {
181  found = true;
182  break;
183  }
184  }
185 
186  // Normalisation coefficient (eq. 11)
187  // Note: sqrt(10*V)/sqrt(nEddy) applied outside when computing uDash
188  c1_ = cmptAv(sigma_)/cmptProduct(sigma_)*cmptMin(sigma_);
189 
190  if (found)
191  {
192  // Shuffle the gamma^2 values
193  rndGen.shuffle(Gamma2);
194  }
195  else
196  {
197  if (debug)
198  {
199  // If not found typically means that the stress has a repeated
200  // eigenvalue/not covered by the selection of Gamma values, e.g.
201  // as seen by range of applicability on Lumley diagram
203  << "Unable to set eddy intensity for eddy: " << *this
204  << endl;
205  }
206 
207  // Remove the influence of this eddy/indicate that its initialisation
208  // failed
209  patchFaceI_ = -1;
210  }
211 }
212 
213 
215 :
216  patchFaceI_(e.patchFaceI_),
217  position0_(e.position0_),
218  x_(e.x_),
219  sigma_(e.sigma_),
220  alpha_(e.alpha_),
221  Rpg_(e.Rpg_),
222  c1_(e.c1_),
223  dir1_(e.dir1_)
224 {}
225 
226 
227 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
228 
229 Foam::vector Foam::eddy::uDash(const point& xp, const vector& n) const
230 {
231  // Relative position inside eddy (global system)
232  const vector r = cmptDivide(xp - position(n), sigma_);
233 
234  if (mag(r) > 1)
235  {
236  return vector::zero;
237  }
238 
239  // Relative position inside eddy (eddy principal system)
240  const vector rp = Rpg_.T() & r;
241 
242  // Shape function (eddy principal system)
243  const vector q = cmptMultiply(sigma_, vector::one - cmptMultiply(rp, rp));
244 
245  // Fluctuating velocity (eddy principal system) (eq. 8)
246  const vector uDashp = cmptMultiply(q, rp^alpha_);
247 
248  // Convert into global system (eq. 10)
249  return c1_*(Rpg_ & uDashp);
250 }
251 
252 
254 (
255  const vector& n,
256  Ostream& os
257 ) const
258 {
259  point p = position(n);
260  os << "v " << p.x() << " " << p.y() << " " << p.z() << nl;
261 }
262 
263 
264 Foam::label Foam::eddy::writeSurfaceOBJ
265 (
266  const label pointOffset,
267  const vector& n,
268  Ostream& os
269 ) const
270 {
271  if (patchFaceI_ < 0)
272  {
273  // Invalid eddy
274  return 0;
275  }
276 
277  static const label nFaceAxis = 20;
278  static const label nFaceTheta = 22;
279  static const label nEddyPoints = (nFaceAxis - 1)*nFaceTheta + 2;
281 
282  static scalar dTheta = mathematical::twoPi/nFaceTheta;
283  static scalar dPhi = mathematical::pi/scalar(nFaceAxis);
284 
285  label pointI = pointOffset;
286 
287  const vector& s = sigma_;
288 
289  const vector axisDir = tensor::I.vectorComponent(dir1_);
290  const label dir2 = (dir1_ + 1) % 3;
291  const label dir3 = (dir1_ + 2) % 3;
292 
293  // Calculate the point positions
294  x[0] = axisDir*s[dir1_];
295  x[nEddyPoints - 1] = - axisDir*s[dir1_];
296 
297  label eddyPtI = 1;
298  for (label axisI = 1; axisI < nFaceAxis; axisI++)
299  {
300  scalar z = s[dir1_]*cos(axisI*dPhi);
301  scalar r = sqrt(sqr(s[dir2])*(1 - sqr(z)/sqr(s[dir1_])));
302 
303  for (label thetaI = 0; thetaI < nFaceTheta; thetaI++)
304  {
305  scalar theta = thetaI*dTheta;
306  point& p = x[eddyPtI++];
307  p[dir1_] = z;
308  p[dir2] = r*sin(theta);
309  p[dir3] = r*cos(theta);
310  }
311  }
312 
313  // Write points
314  forAll(x, i)
315  {
316  point p = position(n) + (Rpg_ & x[i]);
317  os << "v " << p.x() << " " << p.y() << " " << p.z() << nl;
318  }
319 
320  // Write the end cap tri faces
321  for (label faceI = 0; faceI < nFaceTheta; faceI++)
322  {
323  label p1 = pointI + 1;
324  label p2 = p1 + faceI + 1;
325  label p3 = p2 + 1;
326  if (faceI == nFaceTheta - 1) p3 -= nFaceTheta;
327  os << "f " << p1 << " " << p2 << " " << p3 << nl;
328 
329  label q1 = pointI + nEddyPoints;
330  label q2 = q1 - faceI - 1;
331  label q3 = q2 - 1;
332  if (faceI == nFaceTheta - 1) q3 += nFaceTheta;
333  os << "f " << q1 << " " << q2 << " " << q3 << nl;
334  }
335 
336  // Write quad faces
337  for (label axisI = 1; axisI < nFaceAxis - 1; axisI++)
338  {
339  for (label thetaI = 0; thetaI < nFaceTheta; thetaI++)
340  {
341  label p1 = pointI + 1 + (axisI - 1)*nFaceTheta + thetaI + 1;
342  label p2 = p1 + nFaceTheta;
343  label p3 = p2 + 1;
344  label p4 = p1 + 1;
345 
346  if (thetaI == nFaceTheta - 1)
347  {
348  p3 -= nFaceTheta;
349  p4 -= nFaceTheta;
350  }
351  os << "f " << p1 << " " << p2 << " " << p3 << " " << p4 << nl;
352  }
353  }
354 
355  return nEddyPoints;
356 }
357 
358 
359 // ************************************************************************* //
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< Cmpt >, Cmpt, 3 >::one
static const Vector< Cmpt > one
Definition: VectorSpace.H:116
Foam::eddy::debug
static int debug
Definition: eddy.H:143
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:254
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:592
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:350
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:265
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:115
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)
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::eddy::uDash
vector uDash(const point &xp, const vector &n) const
Return the fluctuating velocity contribution at local point xp.
Definition: eddy.C:229
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:385
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< Cmpt >, Cmpt, 3 >::zero
static const Vector< Cmpt > 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)
rp
regionProperties rp(runTime)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:303
Foam::I
static const Identity< scalar > I
Definition: Identity.H:95
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265