Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
VariableConverter.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File VariableConverter.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Auxiliary functions to convert variables in
33 // the compressible flow system
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 #include <iostream>
37 #include <iomanip>
38 
40 
41 using namespace std;
42 
43 namespace Nektar
44 {
45  VariableConverter::VariableConverter(
47  const int spaceDim)
48  : m_session(pSession),
49  m_spacedim(spaceDim)
50  {
51  m_session->LoadParameter ("Gamma", m_gamma, 1.4);
52  m_session->LoadParameter ("pInf", m_pInf, 101325);
53  m_session->LoadParameter ("rhoInf", m_rhoInf, 1.225);
54  m_session->LoadParameter ("GasConstant", m_gasConstant, 287.058);
55  m_session->LoadParameter ("mu", m_mu, 1.78e-05);
56 
57  if( m_session->DefinesParameter("thermalConductivity"))
58  {
59  ASSERTL0( !m_session->DefinesParameter("Pr"),
60  "Cannot define both Pr and thermalConductivity.");
61 
62  m_session->LoadParameter ("thermalConductivity",
64  }
65  else
66  {
67  NekDouble Pr, Cp;
68  m_session->LoadParameter ("Pr",
69  Pr, 0.72);
70  Cp = m_gamma / (m_gamma - 1.0) * m_gasConstant;
71  m_thermalConductivity = Cp * m_mu / Pr;
72  }
73 
74  // Parameters for sensor
75  m_session->LoadParameter ("Skappa", m_Skappa, -2.048);
76  m_session->LoadParameter ("Kappa", m_Kappa, 0.0);
77  m_session->LoadParameter ("mu0", m_mu0, 1.0);
78  }
79 
80  /**
81  * @brief Destructor for VariableConverter class.
82  */
84  {
85 
86  }
87 
88  /**
89  * @brief Calculate the pressure field \f$ p =
90  * (\gamma-1)(E-\frac{1}{2}\rho\| \mathbf{v} \|^2) \f$ assuming an ideal
91  * gas law.
92  *
93  * @param physfield Input momentum.
94  * @param pressure Computed pressure field.
95  */
97  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
98  Array<OneD, NekDouble> &pressure)
99  {
100  int nPts = physfield[0].num_elements();
101  NekDouble alpha = -0.5;
102 
103  // Calculate ||rho v||^2
104  Vmath::Vmul(nPts, physfield[1], 1, physfield[1], 1, pressure, 1);
105  for (int i = 1; i < m_spacedim; ++i)
106  {
107  Vmath::Vvtvp(nPts, physfield[1+i], 1, physfield[1+i], 1,
108  pressure, 1, pressure, 1);
109  }
110  // Divide by rho to get rho*||v||^2
111  Vmath::Vdiv (nPts, pressure, 1, physfield[0], 1, pressure, 1);
112  // pressure <- E - 0.5*pressure
113  Vmath::Svtvp(nPts, alpha,
114  pressure, 1, physfield[m_spacedim+1], 1, pressure, 1);
115  // Multiply by (gamma-1)
116  Vmath::Smul (nPts, m_gamma-1, pressure, 1, pressure, 1);
117  }
118 
119  /**
120  * @brief Calculate the pressure field \f$ p =
121  * (\gamma-1)(E-\frac{1}{2}\rho\| \mathbf{v} \|^2) \f$ assuming an ideal
122  * gas law.
123  *
124  * This is a slightly optimised way to calculate the pressure field which
125  * avoids division by the density field if the velocity field has already
126  * been calculated.
127  *
128  * @param physfield Input momentum.
129  * @param velocity Velocity vector.
130  * @param pressure Computed pressure field.
131  */
133  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
134  const Array<OneD, const Array<OneD, NekDouble> > &velocity,
135  Array<OneD, NekDouble> &pressure)
136  {
137  int nPts = physfield[0].num_elements();
138  NekDouble alpha = -0.5;
139 
140  // Calculate ||\rho v||^2.
141  Vmath::Vmul (nPts, velocity[0], 1, physfield[1], 1, pressure, 1);
142  for (int i = 1; i < m_spacedim; ++i)
143  {
144  Vmath::Vvtvp(nPts, velocity[i], 1, physfield[1+i], 1,
145  pressure, 1, pressure, 1);
146  }
147  // pressure <- E - 0.5*pressure
148  Vmath::Svtvp(nPts, alpha,
149  pressure, 1, physfield[m_spacedim+1], 1, pressure, 1);
150  // Multiply by (gamma-1).
151  Vmath::Smul (nPts, m_gamma-1, pressure, 1, pressure, 1);
152  }
153 
154  /**
155  * @brief Compute the enthalpy term \f$ H = E + p/rho \$.
156  */
158  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
159  Array<OneD, NekDouble> &pressure,
160  Array<OneD, NekDouble> &enthalpy)
161  {
162  int nPts = physfield[0].num_elements();
163  Array<OneD, NekDouble> tmp(nPts, 0.0);
164 
165  // Calculate E = rhoE/rho
166  Vmath::Vdiv(nPts, physfield[m_spacedim+1], 1, physfield[0], 1, tmp, 1);
167  // Calculate p/rho
168  Vmath::Vdiv(nPts, pressure, 1, physfield[0], 1, enthalpy, 1);
169  // Calculate H = E + p/rho
170  Vmath::Vadd(nPts, tmp, 1, enthalpy, 1, enthalpy, 1);
171  }
172 
173  /**
174  * @brief Compute the velocity field \f$ \mathbf{v} \f$ given the momentum
175  * \f$ \rho\mathbf{v} \f$.
176  *
177  * @param physfield Momentum field.
178  * @param velocity Velocity field.
179  */
181  const Array<OneD, Array<OneD, NekDouble> > &physfield,
182  Array<OneD, Array<OneD, NekDouble> > &velocity)
183  {
184  const int nPts = physfield[0].num_elements();
185 
186  for (int i = 0; i < m_spacedim; ++i)
187  {
188  Vmath::Vdiv(nPts, physfield[1+i], 1, physfield[0], 1,
189  velocity[i], 1);
190  }
191  }
192 
193  /**
194  * @brief Compute the temperature \f$ T = p/\rho R \f$.
195  *
196  * @param physfield Input physical field.
197  * @param pressure The pressure field corresponding to physfield.
198  * @param temperature The resulting temperature \f$ T \f$.
199  */
201  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
202  Array<OneD, NekDouble > &pressure,
203  Array<OneD, NekDouble > &temperature)
204  {
205  const int nPts = physfield[0].num_elements();
206 
207  Vmath::Vdiv(nPts, pressure, 1, physfield[0], 1, temperature, 1);
208  Vmath::Smul(nPts, 1.0/m_gasConstant, temperature, 1, temperature, 1);
209  }
210 
211  /**
212  * @brief Compute the sound speed \f$ c = sqrt(\gamma p/\rho) \f$.
213  *
214  * @param physfield Input physical field.
215  * @param pressure The pressure field corresponding to physfield.
216  * @param soundspeed The resulting sound speed \f$ c \f$.
217  */
219  const Array<OneD, Array<OneD, NekDouble> > &physfield,
220  Array<OneD, NekDouble > &pressure,
221  Array<OneD, NekDouble > &soundspeed)
222  {
223  const int nPts = physfield[0].num_elements();
224  Vmath::Vdiv (nPts, pressure, 1, physfield[0], 1, soundspeed, 1);
225  Vmath::Smul (nPts, m_gamma, soundspeed, 1, soundspeed, 1);
226  Vmath::Vsqrt(nPts, soundspeed, 1, soundspeed, 1);
227  }
228 
229  /**
230  * @brief Compute the mach number \f$ M = \| \mathbf{v} \|^2 / c \f$.
231  *
232  * @param physfield Input physical field.
233  * @param soundfield The speed of sound corresponding to physfield.
234  * @param mach The resulting mach number \f$ M \f$.
235  */
237  Array<OneD, Array<OneD, NekDouble> > &physfield,
238  Array<OneD, NekDouble > &soundspeed,
239  Array<OneD, NekDouble > &mach)
240  {
241  const int nPts = physfield[0].num_elements();
242 
243  Vmath::Vmul(nPts, physfield[1], 1, physfield[1], 1, mach, 1);
244 
245  for (int i = 1; i < m_spacedim; ++i)
246  {
247  Vmath::Vvtvp(nPts, physfield[1+i], 1, physfield[1+i], 1,
248  mach, 1, mach, 1);
249  }
250 
251  Vmath::Vdiv(nPts, mach, 1, physfield[0], 1, mach, 1);
252  Vmath::Vdiv(nPts, mach, 1, physfield[0], 1, mach, 1);
253  Vmath::Vsqrt(nPts, mach, 1, mach, 1);
254 
255  Vmath::Vdiv(nPts, mach, 1, soundspeed, 1, mach, 1);
256  }
257 
258  /**
259  * @brief Compute the dynamic viscosity using the Sutherland's law
260  * \f$ \mu = \mu_star * (T / T_star)^3/2 * (T_star + 110) / (T + 110) \f$,
261  * where: \mu_star = 1.7894 * 10^-5 Kg / (m * s)
262  * T_star = 288.15 K
263  *
264  * @param physfield Input physical field.
265  * @param mu The resulting dynamic viscosity.
266  */
268  const Array<OneD, const NekDouble> &temperature,
269  Array<OneD, NekDouble> &mu)
270  {
271  const int nPts = temperature.num_elements();
272  NekDouble mu_star = m_mu;
273  NekDouble T_star = m_pInf / (m_rhoInf * m_gasConstant);
274  NekDouble ratio;
275 
276  for (int i = 0; i < nPts; ++i)
277  {
278  ratio = temperature[i] / T_star;
279  mu[i] = mu_star * ratio * sqrt(ratio) *
280  (T_star + 110.0) / (temperature[i] + 110.0);
281  }
282  }
283 
284  /**
285  * @brief Calculate entropy.
286  */
288  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
289  const Array<OneD, const NekDouble> &pressure,
290  const Array<OneD, const NekDouble> &temperature,
291  Array<OneD, NekDouble> &entropy)
292  {
293  const int nPts = physfield[0].num_elements();
294  const NekDouble temp_inf = m_pInf/(m_rhoInf*m_gasConstant);;
295 
296  for (int i = 0; i < nPts; ++i)
297  {
298  entropy[i] = m_gamma / (m_gamma - 1.0) * m_gasConstant *
299  log(temperature[i]/temp_inf) - m_gasConstant *
300  log(pressure[i] / m_pInf);
301  }
302  }
303 
305  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
306  Array<OneD, NekDouble> &Vtot)
307  {
308  const int nPts = inarray[0].num_elements();
309 
310  // Getting the velocity vector on the 2D normal space
311  Array<OneD, Array<OneD, NekDouble> > velocity (m_spacedim);
312 
313  Vmath::Zero(Vtot.num_elements(), Vtot, 1);
314 
315  for (int i = 0; i < m_spacedim; ++i)
316  {
317  velocity[i] = Array<OneD, NekDouble>(nPts);
318  }
319 
320  GetVelocityVector(inarray, velocity);
321 
322  for (int i = 0; i < m_spacedim; ++i)
323  {
324  Vmath::Vvtvp(nPts,
325  velocity[i], 1,
326  velocity[i], 1,
327  Vtot, 1,
328  Vtot, 1);
329  }
330 
331  Vmath::Vsqrt(nPts,Vtot,1,Vtot,1);
332  }
333 
335  const MultiRegions::ExpListSharedPtr &field,
336  const Array<OneD, const Array<OneD, NekDouble> > &physarray,
337  Array<OneD, NekDouble> &Sensor,
338  Array<OneD, NekDouble> &SensorKappa)
339  {
340  int e, NumModesElement, nQuadPointsElement;
341  int nTotQuadPoints = field->GetTotPoints();
342  int nElements = field->GetExpSize();
343 
344  // Find solution (SolP) at p = P;
345  // The input array (physarray) is the solution at p = P;
346 
347  Array<OneD,int> ExpOrderElement = field->EvalBasisNumModesMaxPerExp();
348 
349  Array<OneD, NekDouble> SolP (nTotQuadPoints, 0.0);
350  Array<OneD, NekDouble> SolPmOne(nTotQuadPoints, 0.0);
351  Array<OneD, NekDouble> SolNorm (nTotQuadPoints, 0.0);
352 
353  Vmath::Vcopy(nTotQuadPoints, physarray[0], 1, SolP, 1);
354 
355  int CoeffsCount = 0;
356 
357  for (e = 0; e < nElements; e++)
358  {
359  NumModesElement = ExpOrderElement[e];
360  int nQuadPointsElement = field->GetExp(e)->GetTotPoints();
361  int nCoeffsElement = field->GetExp(e)->GetNcoeffs();
362  int numCutOff = NumModesElement - 1;
363 
364  // Set-up of the Orthogonal basis for a Quadrilateral element which
365  // is needed to obtain thesolution at P = p - 1;
366 
367  Array<OneD, NekDouble> SolPElementPhys (nQuadPointsElement, 0.0);
368  Array<OneD, NekDouble> SolPElementCoeffs(nCoeffsElement, 0.0);
369 
370  Array<OneD, NekDouble> SolPmOneElementPhys(nQuadPointsElement, 0.0);
371  Array<OneD, NekDouble> SolPmOneElementCoeffs(nCoeffsElement, 0.0);
372 
373  // create vector the save the solution points per element at P = p;
374 
375  for (int i = 0; i < nQuadPointsElement; i++)
376  {
377  SolPElementPhys[i] = SolP[CoeffsCount+i];
378  }
379 
380  field->GetExp(e)->FwdTrans(SolPElementPhys,
381  SolPElementCoeffs);
382 
383  // ReduceOrderCoeffs reduces the polynomial order of the solution
384  // that is represented by the coeffs given as an inarray. This is
385  // done by projecting the higher order solution onto the orthogonal
386  // basis and padding the higher order coefficients with zeros.
387 
388  field->GetExp(e)->ReduceOrderCoeffs(numCutOff,
389  SolPElementCoeffs,
390  SolPmOneElementCoeffs);
391 
392  field->GetExp(e)->BwdTrans(SolPmOneElementCoeffs,
393  SolPmOneElementPhys);
394 
395  for (int i = 0; i < nQuadPointsElement; i++)
396  {
397  SolPmOne[CoeffsCount+i] = SolPmOneElementPhys[i];
398  }
399 
400  NekDouble SolPmeanNumerator = 0.0;
401  NekDouble SolPmeanDenumerator = 0.0;
402 
403  // Determining the norm of the numerator of the Sensor
404 
405  Vmath::Vsub(nQuadPointsElement,
406  SolPElementPhys, 1,
407  SolPmOneElementPhys, 1,
408  SolNorm, 1);
409 
410  Vmath::Vmul(nQuadPointsElement,
411  SolNorm, 1,
412  SolNorm, 1,
413  SolNorm, 1);
414 
415  for (int i = 0; i < nQuadPointsElement; i++)
416  {
417  SolPmeanNumerator += SolNorm[i];
418  SolPmeanDenumerator += SolPElementPhys[i];
419  }
420 
421  for (int i = 0; i < nQuadPointsElement; ++i)
422  {
423  Sensor[CoeffsCount+i] =
424  sqrt(SolPmeanNumerator / nQuadPointsElement) /
425  sqrt(SolPmeanDenumerator / nQuadPointsElement);
426 
427  Sensor[CoeffsCount+i] = log10(Sensor[CoeffsCount+i]);
428  }
429  CoeffsCount += nQuadPointsElement;
430  }
431 
432  CoeffsCount = 0.0;
433 
434  for (e = 0; e < nElements; e++)
435  {
436  NumModesElement = ExpOrderElement[e];
437  NekDouble ThetaS = m_mu0;
438  NekDouble Phi0 = m_Skappa;
439  NekDouble DeltaPhi = m_Kappa;
440  nQuadPointsElement = field->GetExp(e)->GetTotPoints();
441 
442  for (int i = 0; i < nQuadPointsElement; i++)
443  {
444  if (Sensor[CoeffsCount+i] <= (Phi0 - DeltaPhi))
445  {
446  SensorKappa[CoeffsCount+i] = 0;
447  }
448  else if(Sensor[CoeffsCount+i] >= (Phi0 + DeltaPhi))
449  {
450  SensorKappa[CoeffsCount+i] = ThetaS;
451  }
452  else if(abs(Sensor[CoeffsCount+i]-Phi0) < DeltaPhi)
453  {
454  SensorKappa[CoeffsCount+i] =
455  ThetaS / 2 * (1 + sin(M_PI * (Sensor[CoeffsCount+i] -
456  Phi0) / (2 * DeltaPhi)));
457  }
458  }
459 
460  CoeffsCount += nQuadPointsElement;
461  }
462  }
463 
464 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:408
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
svtvp (scalar times vector plus vector): z = alpha*x + y
Definition: Vmath.cpp:485
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:442
void GetEnthalpy(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &pressure, Array< OneD, NekDouble > &enthalpy)
STL namespace.
void Vdiv(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x/y.
Definition: Vmath.cpp:241
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:51
LibUtilities::SessionReaderSharedPtr m_session
void GetDynamicViscosity(const Array< OneD, const NekDouble > &temperature, Array< OneD, NekDouble > &mu)
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*y.
Definition: Vmath.cpp:213
void GetAbsoluteVelocity(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, NekDouble > &Vtot)
void GetSoundSpeed(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &pressure, Array< OneD, NekDouble > &soundspeed)
~VariableConverter()
Destructor for VariableConverter class.
boost::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
void GetSensor(const MultiRegions::ExpListSharedPtr &field, const Array< OneD, const Array< OneD, NekDouble > > &physarray, Array< OneD, NekDouble > &Sensor, Array< OneD, NekDouble > &SensorKappa)
double NekDouble
void GetVelocityVector(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, NekDouble > > &velocity)
void GetEntropy(const Array< OneD, const Array< OneD, NekDouble > > &physfield, const Array< OneD, const NekDouble > &pressure, const Array< OneD, const NekDouble > &temperature, Array< OneD, NekDouble > &entropy)
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition: Vmath.cpp:343
void GetMach(Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &soundspeed, Array< OneD, NekDouble > &mach)
void GetPressure(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &pressure)
Calculate the pressure field assuming an ideal gas law.
void GetTemperature(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &pressure, Array< OneD, NekDouble > &temperature)
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:373
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1061
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:299
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:183