Nektar++
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 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Auxiliary functions to convert variables in
32 // the compressible flow system
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 #include <iomanip>
36 #include <iostream>
37 
39 
40 using namespace std;
41 
42 namespace Nektar
43 {
44 VariableConverter::VariableConverter(
45  const LibUtilities::SessionReaderSharedPtr &pSession, const int spaceDim)
46  : m_session(pSession), m_spacedim(spaceDim)
47 {
48  // Create equation of state object
49  std::string eosType;
50  m_session->LoadSolverInfo("EquationOfState", eosType, "IdealGas");
52 
53  // Parameters for dynamic viscosity
54  m_session->LoadParameter("pInf", m_pInf, 101325);
55  m_session->LoadParameter("rhoInf", m_rhoInf, 1.225);
56  m_session->LoadParameter("GasConstant", m_gasConstant, 287.058);
57  m_session->LoadParameter("mu", m_mu, 1.78e-05);
58 
59  // Parameters for sensor
60  m_session->LoadParameter("Skappa", m_Skappa, -1.0);
61  m_session->LoadParameter("Kappa", m_Kappa, 0.25);
62 
63 }
64 
65 /**
66  * @brief Destructor for VariableConverter class.
67  */
69 {
70 }
71 
72 /**
73  * @brief Compute the specific internal energy
74  * \f$ e = (E - rho*V^2/2)/rho \f$.
75  */
77  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
78  Array<OneD, NekDouble> &energy)
79 {
80  int nPts = physfield[0].num_elements();
81  Array<OneD, NekDouble> tmp(nPts, 0.0);
82 
83  // tmp = (rho * u_i)^2
84  for (int i = 0; i < m_spacedim; ++i)
85  {
86  Vmath::Vvtvp(nPts, physfield[i + 1], 1, physfield[i + 1], 1, tmp, 1,
87  tmp, 1);
88  }
89  // Divide by rho and multiply by 0.5 --> tmp = 0.5 * rho * u^2
90  Vmath::Vdiv(nPts, tmp, 1, physfield[0], 1, tmp, 1);
91  Vmath::Smul(nPts, 0.5, tmp, 1, tmp, 1);
92 
93  // Calculate rhoe = E - rho*V^2/2
94  Vmath::Vsub(nPts, physfield[m_spacedim + 1], 1, tmp, 1, energy, 1);
95  // Divide by rho
96  Vmath::Vdiv(nPts, energy, 1, physfield[0], 1, energy, 1);
97 }
98 
99 /**
100  * @brief Compute the specific enthalpy \f$ h = e + p/rho \f$.
101  */
103  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
104  Array<OneD, NekDouble> &enthalpy)
105 {
106  int nPts = physfield[0].num_elements();
107  Array<OneD, NekDouble> energy(nPts, 0.0);
108  Array<OneD, NekDouble> pressure(nPts, 0.0);
109 
110  GetInternalEnergy(physfield, energy);
111  GetPressure(physfield, pressure);
112 
113  // Calculate p/rho
114  Vmath::Vdiv(nPts, pressure, 1, physfield[0], 1, enthalpy, 1);
115  // Calculate h = e + p/rho
116  Vmath::Vadd(nPts, energy, 1, enthalpy, 1, enthalpy, 1);
117 }
118 
119 /**
120  * @brief Compute the velocity field \f$ \mathbf{v} \f$ given the momentum
121  * \f$ \rho\mathbf{v} \f$.
122  *
123  * @param physfield Momentum field.
124  * @param velocity Velocity field.
125  */
127  const Array<OneD, Array<OneD, NekDouble>> &physfield,
128  Array<OneD, Array<OneD, NekDouble>> &velocity)
129 {
130  const int nPts = physfield[0].num_elements();
131 
132  for (int i = 0; i < m_spacedim; ++i)
133  {
134  Vmath::Vdiv(nPts, physfield[1 + i], 1, physfield[0], 1, velocity[i], 1);
135  }
136 }
137 
138 /**
139  * @brief Compute the mach number \f$ M = \| \mathbf{v} \|^2 / c \f$.
140  *
141  * @param physfield Input physical field.
142  * @param soundfield The speed of sound corresponding to physfield.
143  * @param mach The resulting mach number \f$ M \f$.
144  */
146  Array<OneD, NekDouble> &soundspeed,
148 {
149  const int nPts = physfield[0].num_elements();
150 
151  Vmath::Vmul(nPts, physfield[1], 1, physfield[1], 1, mach, 1);
152 
153  for (int i = 1; i < m_spacedim; ++i)
154  {
155  Vmath::Vvtvp(nPts, physfield[1 + i], 1, physfield[1 + i], 1, mach, 1,
156  mach, 1);
157  }
158 
159  Vmath::Vdiv(nPts, mach, 1, physfield[0], 1, mach, 1);
160  Vmath::Vdiv(nPts, mach, 1, physfield[0], 1, mach, 1);
161  Vmath::Vsqrt(nPts, mach, 1, mach, 1);
162 
163  Vmath::Vdiv(nPts, mach, 1, soundspeed, 1, mach, 1);
164 }
165 
166 /**
167  * @brief Compute the dynamic viscosity using the Sutherland's law
168  * \f$ \mu = \mu_star * (T / T_star)^3/2 * (1 + C) / (T / T_star + C) \f$,
169  * where: \mu_star = 1.7894 * 10^-5 Kg / (m * s)
170  * T_star = 288.15 K
171  * C = 110. / 288.15
172  *
173  * WARNING, if this routine is modified the same must be done in the
174  * FieldConvert utility ProcessWSS.cpp (this class should be restructured).
175  *
176  * @param physfield Input physical field.
177  * @param mu The resulting dynamic viscosity.
178  */
181 {
182  const int nPts = temperature.num_elements();
183  const NekDouble C = .38175;
184  NekDouble mu_star = m_mu;
185  NekDouble T_star = m_pInf / (m_rhoInf * m_gasConstant);
186  NekDouble ratio;
187 
188  for (int i = 0; i < nPts; ++i)
189  {
190  ratio = temperature[i] / T_star;
191  mu[i] = mu_star * ratio * sqrt(ratio) * (1 + C) / (ratio + C);
192  }
193 }
194 
196  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
198 {
199  const int nPts = physfield[0].num_elements();
200 
201  // Getting the velocity vector on the 2D normal space
203 
204  Vmath::Zero(Vtot.num_elements(), Vtot, 1);
205 
206  for (int i = 0; i < m_spacedim; ++i)
207  {
208  velocity[i] = Array<OneD, NekDouble>(nPts);
209  }
210 
211  GetVelocityVector(physfield, velocity);
212 
213  for (int i = 0; i < m_spacedim; ++i)
214  {
215  Vmath::Vvtvp(nPts, velocity[i], 1, velocity[i], 1, Vtot, 1, Vtot, 1);
216  }
217 
218  Vmath::Vsqrt(nPts, Vtot, 1, Vtot, 1);
219 }
220 
222  const MultiRegions::ExpListSharedPtr &field,
223  const Array<OneD, const Array<OneD, NekDouble>> &physarray,
224  Array<OneD, NekDouble> &Sensor, Array<OneD, NekDouble> &SensorKappa,
225  int offset)
226 {
227  NekDouble Skappa;
228  NekDouble order;
230  Array<OneD, int> expOrderElement = field->EvalBasisNumModesMaxPerExp();
231 
232  for (int e = 0; e < field->GetExpSize(); e++)
233  {
234  int numModesElement = expOrderElement[e];
235  int nElmtPoints = field->GetExp(e)->GetTotPoints();
236  int physOffset = field->GetPhys_Offset(e);
237  int nElmtCoeffs = field->GetExp(e)->GetNcoeffs();
238  int numCutOff = numModesElement - offset;
239 
240  if (numModesElement <= offset)
241  {
242  Vmath::Fill(nElmtPoints, 0.0,
243  tmp = Sensor + physOffset, 1);
244  Vmath::Fill(nElmtPoints, 0.0,
245  tmp = SensorKappa + physOffset, 1);
246  continue;
247  }
248 
249  // create vector to save the solution points per element at P = p;
250  Array<OneD, NekDouble> elmtPhys(nElmtPoints,
251  tmp = physarray[0] + physOffset);
252  // Compute coefficients
253  Array<OneD, NekDouble> elmtCoeffs(nElmtCoeffs, 0.0);
254  field->GetExp(e)->FwdTrans(elmtPhys, elmtCoeffs);
255 
256  // ReduceOrderCoeffs reduces the polynomial order of the solution
257  // that is represented by the coeffs given as an inarray. This is
258  // done by projecting the higher order solution onto the orthogonal
259  // basis and padding the higher order coefficients with zeros.
260  Array<OneD, NekDouble> reducedElmtCoeffs(nElmtCoeffs, 0.0);
261  field->GetExp(e)->ReduceOrderCoeffs(numCutOff, elmtCoeffs,
262  reducedElmtCoeffs);
263 
264  Array<OneD, NekDouble> reducedElmtPhys(nElmtPoints, 0.0);
265  field->GetExp(e)->BwdTrans(reducedElmtCoeffs, reducedElmtPhys);
266 
267  NekDouble numerator = 0.0;
268  NekDouble denominator = 0.0;
269 
270  // Determining the norm of the numerator of the Sensor
271  Array<OneD, NekDouble> difference(nElmtPoints, 0.0);
272  Vmath::Vsub(nElmtPoints, elmtPhys, 1, reducedElmtPhys, 1, difference,
273  1);
274 
275  numerator = Vmath::Dot(nElmtPoints, difference, difference);
276  denominator = Vmath::Dot(nElmtPoints, elmtPhys, elmtPhys);
277 
278  NekDouble elmtSensor = sqrt(numerator / denominator);
279  elmtSensor = log10(max(elmtSensor, NekConstants::kNekSqrtTol));
280 
281  Vmath::Fill(nElmtPoints, elmtSensor, tmp = Sensor + physOffset, 1);
282 
283  // Compute reference value for sensor
284  order = max(numModesElement-1, 1);
285  if (order > 0 )
286  {
287  Skappa = m_Skappa - 4.25 * log10(static_cast<NekDouble>(order));
288  }
289  else
290  {
291  Skappa = 0.0;
292  }
293 
294  // Compute artificial viscosity
295  NekDouble elmtSensorKappa;
296  if (elmtSensor < (Skappa-m_Kappa))
297  {
298  elmtSensorKappa = 0;
299  }
300  else if (elmtSensor > (Skappa + m_Kappa))
301  {
302  elmtSensorKappa = 1.0;
303  }
304  else
305  {
306  elmtSensorKappa = 0.5 *
307  (1 + sin(M_PI * (elmtSensor - Skappa) / (2 * m_Kappa)));
308  }
309  Vmath::Fill(nElmtPoints, elmtSensorKappa,
310  tmp = SensorKappa + physOffset, 1);
311  }
312 }
313 
314 /**
315  * @brief Calculate the pressure using the equation of state.
316  *
317  * @param physfield Input momentum.
318  * @param pressure Computed pressure field.
319  */
321  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
323 {
324  int nPts = physfield[0].num_elements();
325 
326  Array<OneD, NekDouble> energy(nPts);
327  GetInternalEnergy(physfield, energy);
328 
329  for (int i = 0; i < nPts; ++i)
330  {
331  pressure[i] = m_eos->GetPressure(physfield[0][i], energy[i]);
332  }
333 }
334 
335 /**
336  * @brief Compute the temperature using the equation of state.
337  *
338  * @param physfield Input physical field.
339  * @param temperature The resulting temperature \f$ T \f$.
340  */
342  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
343  Array<OneD, NekDouble> &temperature)
344 {
345  int nPts = physfield[0].num_elements();
346 
347  Array<OneD, NekDouble> energy(nPts);
348  GetInternalEnergy(physfield, energy);
349 
350  for (int i = 0; i < nPts; ++i)
351  {
352  temperature[i] = m_eos->GetTemperature(physfield[0][i], energy[i]);
353  }
354 }
355 
356 /**
357  * @brief Compute the sound speed using the equation of state.
358  *
359  * @param physfield Input physical field
360  * @param soundspeed The resulting sound speed \f$ c \f$.
361  */
363  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
364  Array<OneD, NekDouble> &soundspeed)
365 {
366  int nPts = physfield[0].num_elements();
367 
368  Array<OneD, NekDouble> energy(nPts);
369  GetInternalEnergy(physfield, energy);
370 
371  for (int i = 0; i < nPts; ++i)
372  {
373  soundspeed[i] = m_eos->GetSoundSpeed(physfield[0][i], energy[i]);
374  }
375 }
376 
377 /**
378  * @brief Compute the entropy using the equation of state.
379  *
380  * @param physfield Input physical field
381  * @param soundspeed The resulting sound speed \f$ c \f$.
382  */
384  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
385  Array<OneD, NekDouble> &entropy)
386 {
387  int nPts = physfield[0].num_elements();
388 
389  Array<OneD, NekDouble> energy(nPts);
390  GetInternalEnergy(physfield, energy);
391 
392  for (int i = 0; i < nPts; ++i)
393  {
394  entropy[i] = m_eos->GetEntropy(physfield[0][i], energy[i]);
395  }
396 }
397 
398 /**
399  * @brief Compute \f$ e(rho,p) \f$ using the equation of state.
400  *
401  * @param rho Input density
402  * @param pressure Input pressure
403  * @param energy The resulting internal energy.
404  */
407  Array<OneD, NekDouble> &energy)
408 {
409  int nPts = rho.num_elements();
410 
411  for (int i = 0; i < nPts; ++i)
412  {
413  energy[i] = m_eos->GetEFromRhoP(rho[i], pressure[i]);
414  }
415 }
416 
417 /**
418  * @brief Compute \f$ rho(p,T) \f$ using the equation of state.
419  *
420  * @param pressure Input pressure
421  * @param temperature Input temperature
422  * @param rho The resulting density
423  */
425  const Array<OneD, NekDouble> &temperature,
427 {
428  int nPts = pressure.num_elements();
429 
430  for (int i = 0; i < nPts; ++i)
431  {
432  rho[i] = m_eos->GetRhoFromPT(pressure[i], temperature[i]);
433  }
434 }
435 }
EquationOfStateSharedPtr m_eos
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:411
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
void GetEFromRhoP(const Array< OneD, NekDouble > &rho, const Array< OneD, NekDouble > &pressure, Array< OneD, NekDouble > &energy)
Compute using the equation of state.
void GetPressure(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &pressure)
Calculate the pressure using the equation of state.
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:445
STL namespace.
static const NekDouble kNekSqrtTol
void GetEntropy(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &entropy)
Compute the entropy using the equation of state.
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:244
void GetAbsoluteVelocity(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &Vtot)
LibUtilities::SessionReaderSharedPtr m_session
void GetEnthalpy(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &enthalpy)
Compute the specific enthalpy .
void GetDynamicViscosity(const Array< OneD, const NekDouble > &temperature, Array< OneD, NekDouble > &mu)
Compute the dynamic viscosity using the Sutherland&#39;s law , where: = 1.7894 * 10^-5 Kg / (m * s) T_st...
void GetMach(Array< OneD, Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &soundspeed, Array< OneD, NekDouble > &mach)
Compute the mach number .
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
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:216
void GetSensor(const MultiRegions::ExpListSharedPtr &field, const Array< OneD, const Array< OneD, NekDouble >> &physarray, Array< OneD, NekDouble > &Sensor, Array< OneD, NekDouble > &SensorKappa, int offset=1)
EquationOfStateFactory & GetEquationOfStateFactory()
Declaration of the equation of state factory singleton.
~VariableConverter()
Destructor for VariableConverter class.
void GetTemperature(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &temperature)
Compute the temperature using the equation of state.
double NekDouble
T Dot(int n, const T *w, const T *x)
vvtvp (vector times vector times vector): z = w*x*y
Definition: Vmath.cpp:917
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:346
void GetSoundSpeed(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &soundspeed)
Compute the sound speed using the equation of state.
void GetVelocityVector(const Array< OneD, Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, NekDouble >> &velocity)
Compute the velocity field given the momentum .
void GetInternalEnergy(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &energy)
Compute the specific internal energy .
void GetRhoFromPT(const Array< OneD, NekDouble > &pressure, const Array< OneD, NekDouble > &temperature, Array< OneD, NekDouble > &rho)
Compute using the equation of state.
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:376
std::shared_ptr< SessionReader > SessionReaderSharedPtr
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:302
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:186